1# Copyright 2015 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""A code generator for TPM 2.0 structures.
6
7The structure generator provides classes to create various objects
8(structures, unions, constants, etc.) and then convert the set of generated
9objects into valid C files named tpm_generated.{h,c}.
10
11"""
12
13from __future__ import print_function
14
15import datetime
16import re
17
18from subprocess import call
19
20_BASIC_TYPES = ['uint8_t', 'int8_t', 'uint16_t', 'int16_t', 'uint32_t',
21                'int32_t', 'uint64_t', 'int64_t']
22_OUTPUT_FILE_H = 'tpm_generated.h'
23_OUTPUT_FILE_CC = 'tpm_generated.c'
24COPYRIGHT_HEADER = (
25    '// Copyright %d The Chromium OS Authors. All rights reserved.\n'
26    '// Use of this source code is governed by a BSD-style license that can '
27    'be\n'
28    '// found in the LICENSE file.\n'
29    '\n'
30    '// THIS CODE IS GENERATED - DO NOT MODIFY!\n' %
31    datetime.datetime.now().year)
32HEADER_FILE_GUARD_HEADER = """
33#ifndef %(name)s
34#define %(name)s
35"""
36HEADER_FILE_GUARD_FOOTER = """
37#endif  // %(name)s
38"""
39_HEADER_FILE_INCLUDES = """
40#include <endian.h>
41#include <string.h>
42
43#include "TPM_Types.h"
44#include "Tpm.h"
45"""
46_IMPLEMENTATION_FILE_INCLUDES = """
47#include "tpm_generated.h"
48"""
49# Function signatures for generated marshaling code are specified in TCG TPM2.0
50# Library Specification, Part 4: Supporting Routines, sections 4.2.2 and 4.2.3.
51_MARSHAL_BASIC_TYPE = """
52UINT16 %(type)s_Marshal(%(type)s *source, BYTE **buffer, INT32 *size) {
53  %(type)s value_net = *source;
54  if (!size || *size < sizeof(%(type)s)) {
55    return 0;  // Nothing has been marshaled.
56  }
57  switch (sizeof(%(type)s)) {
58    case 2:
59      value_net = htobe16(*source);
60      break;
61    case 4:
62      value_net = htobe32(*source);
63      break;
64    case 8:
65      value_net = htobe64(*source);
66      break;
67    default:
68      break;
69  }
70  memcpy(*buffer, &value_net, sizeof(%(type)s));
71  *buffer += sizeof(%(type)s);
72  *size -= sizeof(%(type)s);
73  return sizeof(%(type)s);
74}
75
76TPM_RC %(type)s_Unmarshal(%(type)s *target, BYTE **buffer, INT32 *size) {
77  %(type)s value_net = 0;
78  if (!size || *size < sizeof(%(type)s)) {
79    return TPM_RC_INSUFFICIENT;
80  }
81  memcpy(&value_net, *buffer, sizeof(%(type)s));
82  switch (sizeof(%(type)s)) {
83    case 2:
84      *target = be16toh(value_net);
85      break;
86    case 4:
87      *target = be32toh(value_net);
88      break;
89    case 8:
90      *target = be64toh(value_net);
91      break;
92    default:
93      *target = value_net;
94  }
95  *buffer += sizeof(%(type)s);
96  *size -= sizeof(%(type)s);
97  return TPM_RC_SUCCESS;
98}
99"""
100_STANDARD_MARSHAL_DECLARATION = """
101UINT16 %(type)s_Marshal(
102    %(type)s *source,
103    BYTE **buffer,
104    INT32 *size);
105
106TPM_RC %(type)s_Unmarshal(
107    %(type)s *target,
108    BYTE **buffer,
109    INT32 *size);
110"""
111
112
113def _IsTPM2B(name):
114  return name.startswith('TPM2B_')
115
116
117class Field(object):
118  """Represents a field in TPM structure or union.
119
120  This object is used in several not fully overlapping cases, not all
121  attributes apply to all use cases.
122
123  The 'array_size' and 'run_time_size' attributes below are related to the
124  following code example:
125
126  struct {
127    int size;
128    byte array[MAX_SIZE]
129  } object.
130
131  In this structure the actual number of bytes in the array could be anything
132  from zero to MAX_SIZE. The field 'size' denotes the actual number of
133  elements at run time. So, when this object is constructed, array_size is
134  'MAX_SIZE' and run_time_size is 'size'.
135
136  The 'selector_value' attribute is used to associate union fields with
137  certain object types. For instance
138
139  typedef union {
140    TPM2B_PUBLIC_KEY_RSA  rsa;
141    TPMS_ECC_POINT        ecc;
142  } TPMU_PUBLIC_ID;
143
144  the field named 'rsa' will have its 'selector_value' set to 'TPM_ALG_RSA'.
145
146  Attributes:
147    field_type: a string, the type of field.
148    field_name: a string, the name of the field.
149    array_size: a string, see example above
150    run_time_size: a string, see example above
151    selector_value: a string, see example above
152    conditional_value: a string, necessary for validation when unmarshaling.
153                       Some types have a value that is allowed for some
154                       commands but not others. E.g. 'TPM_RS_PW' is a
155                       conditional value for the 'TPMI_SH_AUTH_SESSION' type
156                       and TPM_ALG_NULL is a conditional value for the
157                       TPMI_ALG_HASH type.
158  """
159  _MARSHAL_FIELD_ARRAY = """
160  for (i = 0; i < source->%(array_length)s; ++i) {
161    total_size += %(type)s_Marshal(&source->%(name)s[i], buffer, size);
162  }"""
163  _UNMARSHAL_FIELD_ARRAY = """
164  for (i = 0; i < target->%(array_length)s; ++i) {
165    result = %(type)s_Unmarshal(&target->%(name)s[i], buffer, size);
166    if (result != TPM_RC_SUCCESS) {
167      return result;
168    }
169  }"""
170
171  def __init__(self, field_type, field_name,
172               selector=None, array_size='',
173               conditional_value='FALSE',
174               run_time_size=None):
175    """Initializes a Field instance.
176
177    Args:
178      field_type: Initial value for the field type attribute.
179      field_name: Initial value for the field name attribute.
180      selector: Initial value for the selector attribute.
181      array_size: Initial value for the array_size attribute.
182      conditional_value: Initial value of the conditional_value attribute.
183      run_time_size: Initial value of the run_time_size attribute
184    """
185    if not field_type:
186      # Some tables include rows without data type, for instance 'Table 70 -
187      # Definition of TPMU_HA Union' in part 2. These rows are supposed to
188      # cause another case added to the switch in the marshaling function
189      # (processing of TPM_ALG_NULL in this example). Setting field name to ''
190      # makes sure that the actual generated structure/union does not have an
191      # entry for this field, setting type of such field to some value
192      # simplifies functions generating the marshaling code.
193      self.field_type = 'BYTE'
194      self.field_name = ''
195    else:
196      self.field_type = field_type
197      self.field_name = field_name
198    self.array_size = array_size
199    self.selector_value = selector
200    self.conditional_value = conditional_value
201    self.run_time_size = run_time_size
202
203  def OutputMarshal(self, out_file, typemap):
204    """Write a call to marshal the field this instance represents.
205
206    Args:
207      out_file: The output file.
208      typemap: A dict mapping type names to the corresponding object.
209    """
210    if self.array_size:
211      if self.run_time_size:
212        real_size = self.run_time_size
213      else:
214        real_size = self.array_size
215      out_file.write(
216          self._MARSHAL_FIELD_ARRAY % {'type': self.field_type,
217                                       'name': self.field_name,
218                                       'array_length': real_size})
219    else:
220      typemap[self.field_type].OutputMarshalCall(out_file, self)
221
222  def OutputUnmarshal(self, out_file, typemap):
223    """Write a call to unmarshal the field this instance represents.
224
225    Args:
226      out_file: The output file.
227      typemap: A dict mapping type names to the corresponding object.
228    """
229    if self.array_size:
230      if self.run_time_size:
231        real_size = self.run_time_size
232      else:
233        real_size = self.array_size
234      out_file.write(
235          self._UNMARSHAL_FIELD_ARRAY % {'type': self.field_type,
236                                         'name': self.field_name,
237                                         'array_length': real_size})
238    else:
239      typemap[self.field_type].OutputUnmarshalCall(out_file, self)
240
241
242class TPMType(object):
243  """Base type for all TPMTypes.
244
245     Contains functions and string literals common to all TPM types.
246
247     Attributes:
248      _base_type: a string, when set - the very basic type this type is
249                  derived from (should be used for marshaling/unmarshaling to
250                  shortcut multiple nested invocations).
251  """
252  # A function to marshal a TPM typedef.
253  _TYPEDEF_MARSHAL_FUNCTION = """
254UINT16 %(new_type)s_Marshal(
255    %(new_type)s *source,
256    BYTE **buffer,
257    INT32 *size) {
258  return %(old_type)s_Marshal(source, buffer, size);
259}
260"""
261  # The function signature and unmarshaling call to the base type of a TPM
262  # typedef. After the value is unmarshaled, additional validation code is
263  # generated based on tables in TCG TPM2.0 Library Specification, Part 2:
264  # Structures.
265  _TYPEDEF_UNMARSHAL_START = """
266TPM_RC %(new_type)s_Unmarshal(
267    %(new_type)s *target,
268    BYTE **buffer,
269    INT32 *size) {
270  TPM_RC result;
271  result = %(old_type)s_Unmarshal(target, buffer, size);
272  if (result != TPM_RC_SUCCESS) {
273    return result;
274  }"""
275  _UNMARSHAL_END = '\n  return TPM_RC_SUCCESS;\n}\n'
276  # Snippets of code for value validation.
277  _VALUE_START_SWITCH = '\n  switch (%(name)s) {'
278  _VALUE_CASE = '\n    case %(value)s:'
279  _VALUE_CASE_IFDEF = '\n#ifdef %(value)s\n    case %(value)s:\n#endif'
280  _VALUE_END_SWITCH = """
281      break;
282    default:
283      return %(error_code)s;
284  }"""
285  # A declaration for marshaling and unmarshaling functions for a TPM type.
286  _MARSHAL_DECLARATION = _STANDARD_MARSHAL_DECLARATION
287  # Snippets of code which make calls to marshaling functions. Marshals a value
288  # of type 'type' into a field 'name' within a structure. This is used in
289  # generation of structure and command marshaling code.
290  _MARSHAL_CALL = """
291  total_size += %(type)s_Marshal(
292      &source->%(name)s, buffer, size);"""
293  _UNMARSHAL_CALL = """
294  result = %(type)s_Unmarshal(
295      &target->%(name)s, buffer, size);
296  if (result != TPM_RC_SUCCESS) {
297    return result;
298  }"""
299
300  def __init__(self):
301    self._base_type = None
302
303  def SetBaseType(self, base_type):
304    self._base_type = base_type
305
306  def _GetBaseType(self, out_file, marshalled_types, typemap):
307    '''Return base type for this object.
308
309    The base type is used for shortcutting marshaling/unmarshaling code.
310
311    If _base_type is not set, return the old_type value as the base type.
312
313    If the base type's marshaling/unmarshaling code has not been generated
314    yet, issue it before continuing processing.
315
316    Args:
317      out_file: The output file.
318      marshalled_types: A set of types for which marshal and unmarshal functions
319          have already been generated.
320      typemap: A dict mapping type names to the corresponding object.
321
322    Returns:
323      A string, the name of the type to use for marshaling/unmarshaling.
324
325    '''
326    if self._base_type:
327      base_type = self._base_type
328    else:
329      base_type = self.old_type
330    if base_type not in marshalled_types:
331      typemap[base_type].OutputMarshalImpl(
332        out_file, marshalled_types, typemap)
333    return base_type
334
335  def HasConditional(self):
336    """Returns true if TPMType has a conditional value."""
337    return False
338
339  def OutputMarshalCall(self, out_file, field):
340    """Write a call to Marshal function for TPMType to |out_file|.
341
342       Accumulates a variable 'total_size' with the result of marshaling
343       field |field_name| in structure 'source'.
344
345    Args:
346      out_file: The output file.
347      field: A Field object describing this type.
348    """
349    out_file.write(self._MARSHAL_CALL % {'type': field.field_type,
350                                         'name': field.field_name})
351
352  def OutputUnmarshalCall(self, out_file, field):
353    """Write a call to Unmarshal function for TPMType to |out_file|.
354
355       Assigns result of unmarshaling field |field_name| in structure 'source'
356       to variable 'result'. Returns if the unmarshalling was unsuccessful.
357
358    Args:
359      out_file: The output file.
360      field: A Field object describing this type.
361    """
362    obj_type = field.field_type
363    if obj_type == 'TPM_CC':
364      obj_type = 'UINT32'
365    out_file.write(self._UNMARSHAL_CALL % {'type': obj_type,
366                                           'name': field.field_name})
367
368  def _OutputTypedefMarshalDecl(self, out_file, declared_types, typemap):
369    """Write marshal declarations for TPM typedefs to |out_file|.
370
371       Can only be called on Typedef, ConstantType, AttributeStruct, and
372       Interface objects.
373
374    Args:
375      out_file: The output file.
376      declared_types: A set of types for which marshal and unmarshal function
377          declarations have already been generated.
378      typemap: A dict mapping type names to the corresponding object.
379    """
380    if self.new_type in declared_types:
381      return
382    if self.old_type not in declared_types and self.old_type in typemap:
383      typemap[self.old_type].OutputMarshalDecl(
384          out_file, declared_types, typemap)
385    out_file.write(self._MARSHAL_DECLARATION % {'type': self.new_type})
386    declared_types.add(self.new_type)
387
388  def _OutputStructOrUnionMarshalDecl(self, out_file, declared_types):
389    """Write marshal declarations for a TPM Structure or Union.
390
391       Can only be called on Structure and Union objects.
392
393    Args:
394      out_file: The output file.
395      declared_types: A set of types for which marshal and unmarshal function
396        declarations have already been generated.
397    """
398    # TPMU_NAME and TPMU_ENCRYPTED_SECRET type are never used across the
399    # interface.
400    if (self.name in declared_types or
401        self.name == 'TPMU_NAME' or
402        self.name == 'TPMU_ENCRYPTED_SECRET'):
403      return
404    out_file.write(self._MARSHAL_DECLARATION % {'type': self.name})
405    declared_types.add(self.name)
406
407
408class Typedef(TPMType):
409  """Represents a TPM typedef.
410
411  Attributes:
412    old_type: The existing type in a typedef statement.
413    new_type: The new type in a typedef statement.
414  """
415  # A function to unmarshal a TPM typedef with no extra validation.
416  _TYPEDEF_UNMARSHAL_FUNCTION = """
417TPM_RC %(new_type)s_Unmarshal(
418    %(new_type)s *target,
419    BYTE **buffer,
420    INT32 *size) {
421  return %(old_type)s_Unmarshal(target, buffer, size);
422}
423"""
424
425  def __init__(self, old_type, new_type):
426    """Initializes a Typedef instance.
427
428    Args:
429      old_type: The base type of the attribute structure.
430      new_type: The name of the type.
431    """
432    super(Typedef, self).__init__()
433    self.old_type = old_type
434    self.new_type = new_type
435
436  def OutputMarshalImpl(self, out_file, marshalled_types, typemap):
437    """Writes marshal implementations for Typedef to |out_file|.
438
439    Args:
440      out_file: The output file.
441      marshalled_types: A set of types for which marshal and unmarshal functions
442          have already been generated.
443      typemap: A dict mapping type names to the corresponding object.
444    """
445    if self.new_type in marshalled_types:
446      return
447    base_type = self._GetBaseType(out_file, marshalled_types, typemap)
448    out_file.write(self._TYPEDEF_MARSHAL_FUNCTION % {'old_type': base_type,
449                                                     'new_type': self.new_type})
450    out_file.write(
451        self._TYPEDEF_UNMARSHAL_FUNCTION % {'old_type': base_type,
452                                            'new_type': self.new_type})
453    marshalled_types.add(self.new_type)
454
455  def OutputMarshalDecl(self, out_file, declared_types, typemap):
456    """Writes marshal declarations for Typedef to |out_file|.
457
458    Args:
459      out_file: The output file.
460      declared_types: A set of types for which marshal and unmarshal function
461          declarations have already been generated.
462      typemap: A dict mapping type names to the corresponding object.
463    """
464    self._OutputTypedefMarshalDecl(out_file, declared_types, typemap)
465
466
467class ConstantType(TPMType):
468  """Represents a TPM Constant type definition.
469
470  Attributes:
471     old_type: The base type of the constant (e.g. 'int').
472     new_type: The name of the type (e.g. 'TPM_RC').
473     valid_values: The list of valid values this type can take (e.g.
474         'TPM_RC_SUCCESS').
475     error_code: Error to be returned when unmarshalling is unsuccessful.
476  """
477  _CHECK_VALUE = """
478  if (*target == %(value)s) {
479    return TPM_RC_SUCCESS;
480  }"""
481  _CHECK_VALUE_IFDEF = """
482#ifdef %(value)s
483  if (*target == %(value)s) {
484    return TPM_RC_SUCCESS;
485  }
486#endif"""
487  _UNMARSHAL_END = """
488  return %(error_code)s;
489}
490"""
491  _IFDEF_TYPE_RE = re.compile(r'^TPM_(ALG|CC).*')
492
493  def __init__(self, old_type, new_type):
494    """Initializes a ConstantType instance.
495
496    Values are added to valid_values attribute during parsing.
497
498    Args:
499      old_type: The base type of the constant type.
500      new_type: The name of the type.
501    """
502    super(ConstantType, self).__init__()
503    self.old_type = old_type
504    self.new_type = new_type
505    self.valid_values = []
506    self.error_code = 'TPM_RC_VALUE'
507
508  def _NeedsIfdef(self):
509    """Returns True if new_type is a type which needs ifdef enclosing."""
510    return self._IFDEF_TYPE_RE.search(self.new_type)
511
512  def OutputMarshalImpl(self, out_file, marshalled_types, typemap):
513    """Writes marshal implementations for ConstantType to |out_file|.
514
515    Args:
516      out_file: The output file.
517      marshalled_types: A set of types for which marshal and unmarshal functions
518          have already been generated.
519      typemap: A dict mapping type names to the corresponding object.
520    """
521    if self.new_type in marshalled_types:
522      return
523    base_type = self._GetBaseType(out_file, marshalled_types, typemap)
524    out_file.write(self._TYPEDEF_MARSHAL_FUNCTION % {'old_type': base_type,
525                                                     'new_type': self.new_type})
526    out_file.write(self._TYPEDEF_UNMARSHAL_START % {'old_type': base_type,
527                                                    'new_type': self.new_type})
528    for value in self.valid_values:
529      if self._NeedsIfdef():
530        out_file.write(self._CHECK_VALUE_IFDEF % {'value': value})
531      else:
532        out_file.write(self._CHECK_VALUE % {'value': value})
533    out_file.write(self._UNMARSHAL_END % {'error_code': self.error_code})
534    marshalled_types.add(self.new_type)
535
536  def OutputMarshalDecl(self, out_file, declared_types, typemap):
537    """Writes marshal declarations for ConstantType to |out_file|.
538
539    Args:
540      out_file: The output file.
541      declared_types: A set of types for which marshal and unmarshal function
542          declarations have already been generated.
543      typemap: A dict mapping type names to the corresponding object.
544    """
545    self._OutputTypedefMarshalDecl(out_file, declared_types, typemap)
546
547
548class AttributeStructure(TPMType):
549  """Represents a TPM attribute structure type definition.
550
551  Attributes:
552     old_type: The base type of the constant (e.g. 'int').
553     new_type: The name of the type (e.g. 'TPMA_OBJECT').
554     reserved: The list of bit bounds where bits must be 0 (e.g. ['10_2','3']).
555  """
556  # Attribute structures need an explicit cast to the base type.
557  _ATTRIBUTE_MARSHAL_FUNCTION = """
558UINT16 %(new_type)s_Marshal(
559    %(new_type)s *source,
560    BYTE **buffer,
561    INT32 *size) {
562  return %(old_type)s_Marshal((%(old_type)s*)source, buffer, size);
563}
564"""
565  _ATTRIBUTE_UNMARSHAL_START = """
566TPM_RC %(new_type)s_Unmarshal(
567    %(new_type)s *target,
568    BYTE **buffer,
569    INT32 *size) {
570  TPM_RC result;
571  result = %(old_type)s_Unmarshal((%(old_type)s*)target, buffer, size);
572  if (result != TPM_RC_SUCCESS) {
573    return result;
574  }"""
575  _CHECK_RESERVED = """
576  if (target->reserved%(bits)s != 0) {
577    return TPM_RC_RESERVED_BITS;
578  }"""
579
580  def __init__(self, old_type, new_type):
581    """Initializes an AttributeStructure instance.
582
583    Values may be added to reserved attribute during parsing.
584
585    Args:
586      old_type: The base type of the attribute structure.
587      new_type: The name of the type.
588    """
589    super(AttributeStructure, self).__init__()
590    self.old_type = old_type
591    self.new_type = new_type
592    self.reserved = []
593
594  def OutputMarshalImpl(self, out_file, marshalled_types, typemap):
595    """Writes marshal implementations for AttributStructure to |out_file|.
596
597    Args:
598      out_file: The output file.
599      marshalled_types: A set of types for which marshal and unmarshal functions
600          have already been generated.
601      typemap: A dict mapping type names to the corresponding object.
602    """
603    if self.new_type in marshalled_types:
604      return
605    base_type = self._GetBaseType(out_file, marshalled_types, typemap)
606    out_file.write(self._ATTRIBUTE_MARSHAL_FUNCTION %
607                   {'old_type': base_type,
608                    'new_type': self.new_type})
609    out_file.write(self._ATTRIBUTE_UNMARSHAL_START %
610                   {'old_type': base_type,
611                    'new_type': self.new_type})
612    for bits in self.reserved:
613      out_file.write(self._CHECK_RESERVED % {'bits': bits})
614    out_file.write(self._UNMARSHAL_END)
615    marshalled_types.add(self.new_type)
616
617  def OutputMarshalDecl(self, out_file, declared_types, typemap):
618    """Writes marshal declarations for AttributeStructure to |out_file|.
619
620    Args:
621      out_file: The output file.
622      declared_types: A set of types for which marshal and unmarshal function
623          declarations have already been generated.
624      typemap: A dict mapping type names to the corresponding object.
625    """
626    self._OutputTypedefMarshalDecl(out_file, declared_types, typemap)
627
628
629class Interface(TPMType):
630  """Represents a TPM interface type definition.
631
632  Attributes:
633     old_type: The base type of the interface (e.g. 'TPM_HANDLE').
634     new_type: The name of the type (e.g. 'TPMI_DH_OBJECT').
635     valid_values: List of valid values for new_type. If this is not empty,
636         valid values for new_type is explicitly defined in the spec.
637     bounds: List of pairs representing bounds. If nonempty, target must fall
638         between one of these bounds.
639     conditional_value: Name of conditionally allowed value. If there is no
640         such value, this variable will be None.
641     supported_values: String literal indicating the name of a list of supported
642         values to be substituted at compile time (e.g. 'AES_KEY_SIZES_BITS').
643         If this is not None, valid values for new_type depends on the
644         implementation.
645     error_code: Return code when an unmarshalling error occurs.
646  """
647  _INTERFACE_CONDITIONAL_UNMARSHAL_START = """
648TPM_RC %(new_type)s_Unmarshal(
649    %(new_type)s *target,
650    BYTE **buffer,
651    INT32 *size,
652    BOOL allow_conditional_value) {
653  TPM_RC result;"""
654  _INTERFACE_UNMARSHAL_START = """
655TPM_RC %(new_type)s_Unmarshal(
656    %(new_type)s *target,
657    BYTE **buffer,
658    INT32 *size) {
659  TPM_RC result;"""
660  _UNMARSHAL_VALUE = """
661  result = %(old_type)s_Unmarshal(target, buffer, size);
662  if (result != TPM_RC_SUCCESS) {
663    return result;
664  }"""
665  _UNMARSHAL_VALUE_ALLOW_RC_VALUE = """
666  result = %(old_type)s_Unmarshal(target, buffer, size);
667  if ((result != TPM_RC_VALUE) && (result != TPM_RC_SUCCESS)) {
668    return result;
669  }"""
670  _SETUP_CHECK_SUPPORTED_VALUES = """
671  uint16_t supported_values[] = %(supported_values)s;
672  size_t length = sizeof(supported_values)/sizeof(supported_values[0]);
673  size_t i;
674  BOOL is_supported_value = FALSE;"""
675  _CHECK_SUPPORTED_VALUES = """
676  for (i = 0; i < length; ++i) {
677    if (*target == supported_values[i]) {
678      is_supported_value = TRUE;
679      break;
680    }
681  }
682  if (!is_supported_value) {
683    return %(error_code)s;
684  }"""
685  _CHECK_CONDITIONAL = """
686  if (*target == %(name)s) {
687    return allow_conditional_value ? TPM_RC_SUCCESS : %(error_code)s;
688  }"""
689  _SETUP_CHECK_VALUES = '\n  BOOL has_valid_value = FALSE;'
690  _VALUE_END_SWITCH = """
691      has_valid_value = TRUE;
692      break;
693  }"""
694  _CHECK_BOUND = """
695  if((*target >= %(lower)s) && (*target <= %(upper)s)) {
696    has_valid_value = TRUE;
697  }"""
698  _CHECK_VALUES_END = """
699  if (!has_valid_value) {
700    return %(error_code)s;
701  }"""
702  _CONDITIONAL_MARSHAL_DECLARATION = """
703UINT16 %(type)s_Marshal(
704    %(type)s *source,
705    BYTE **buffer,
706    INT32 *size);
707
708TPM_RC %(type)s_Unmarshal(
709    %(type)s *target,
710    BYTE **buffer,
711    INT32 *size,
712    BOOL allow_conditioanl_value);
713"""
714  _CONDITIONAL_UNMARSHAL_CALL = """
715  result = %(type)s_Unmarshal(
716      &target->%(name)s, buffer, size, %(flag)s);
717  if (result != TPM_RC_SUCCESS) {
718    return result;
719  }"""
720  _IFDEF_TYPE_RE = re.compile(r'^TPMI_(ALG|ECC)_.*')
721
722  def __init__(self, old_type, new_type):
723    """Initializes an Interface instance.
724
725    Values may be added/assigned to valid_values, bounds, conditional_value,
726    supported_values, and error_code attributes new values during parsing.
727
728    Args:
729      old_type: The base type of the interface.
730      new_type: The name of the type.
731    """
732    super(Interface, self).__init__()
733    self.old_type = old_type
734    self.new_type = new_type
735    self.valid_values = []
736    self.bounds = []
737    self.conditional_value = None
738    self.supported_values = None
739    self.error_code = 'TPM_RC_VALUE'
740
741  def HasConditional(self):
742    """Returns true if Interface has a valid conditional_value."""
743    return self.conditional_value is not None
744
745  def _NeedsIfdef(self):
746    """Returns True if new_type is a type which needs ifdef enclosing."""
747    return self._IFDEF_TYPE_RE.search(self.new_type)
748
749  def OutputMarshalImpl(self, out_file, marshalled_types, typemap):
750    """Writes marshal implementation for Interface to |out_file|.
751
752    Args:
753      out_file: The output file.
754      marshalled_types: A set of types for which marshal and unmarshal functions
755          have already been generated.
756      typemap: A dict mapping type names to the corresponding object.
757    """
758    if self.new_type in marshalled_types:
759      return
760    base_type = self._GetBaseType(out_file, marshalled_types, typemap)
761    out_file.write(self._TYPEDEF_MARSHAL_FUNCTION % {'old_type': base_type,
762                                                     'new_type': self.new_type})
763    if self.conditional_value:
764      out_file.write(self._INTERFACE_CONDITIONAL_UNMARSHAL_START %
765                     {'old_type': base_type,
766                      'new_type': self.new_type})
767    else:
768      out_file.write(
769          self._INTERFACE_UNMARSHAL_START % {'old_type': base_type,
770                                             'new_type': self.new_type})
771    # Creating necessary local variables.
772    if self.supported_values:
773      out_file.write(self._SETUP_CHECK_SUPPORTED_VALUES %
774                     {'supported_values': self.supported_values})
775    if len(self.valid_values)+len(self.bounds) > 0:
776      out_file.write(self._SETUP_CHECK_VALUES)
777      out_file.write(self._UNMARSHAL_VALUE_ALLOW_RC_VALUE %
778                     {'old_type': base_type})
779    else:
780      out_file.write(self._UNMARSHAL_VALUE % {'old_type': base_type})
781
782    if self.supported_values:
783      out_file.write(self._CHECK_SUPPORTED_VALUES %
784                     {'supported_values': self.supported_values,
785                      'error_code': self.error_code})
786    if self.conditional_value:
787      out_file.write(
788          self._CHECK_CONDITIONAL % {'name': self.conditional_value,
789                                     'error_code': self.error_code})
790    # Checking for valid values.
791    if len(self.valid_values)+len(self.bounds) > 0:
792      if self.valid_values:
793        out_file.write(self._VALUE_START_SWITCH % {'name': '*target'})
794        for value in self.valid_values:
795          if self._NeedsIfdef():
796            out_file.write(self._VALUE_CASE_IFDEF % {'value': value})
797          else:
798            out_file.write(self._VALUE_CASE % {'value': value})
799        out_file.write(self._VALUE_END_SWITCH)
800      for (lower, upper) in self.bounds:
801        out_file.write(
802            self._CHECK_BOUND % {'lower': lower, 'upper': upper})
803      out_file.write(self._CHECK_VALUES_END % {'error_code': self.error_code})
804
805    out_file.write(self._UNMARSHAL_END)
806    marshalled_types.add(self.new_type)
807
808  def OutputMarshalDecl(self, out_file, declared_types, typemap):
809    """Writes marshal declarations for Interface to |out_file|.
810
811       Outputted declaration depends on whether Interface type has a
812       conditionally valid value.
813
814    Args:
815      out_file: The output file.
816      declared_types: A set of types for which marshal and unmarshal function
817          declarations have already been generated.
818      typemap: A dict mapping type names to the corresponding object.
819    """
820    if self.new_type in declared_types:
821      return
822    if self.old_type not in declared_types:
823      typemap[self.old_type].OutputMarshalDecl(
824          out_file, declared_types, typemap)
825    if self.HasConditional():
826      out_file.write(
827          self._CONDITIONAL_MARSHAL_DECLARATION % {'type': self.new_type})
828    else:
829      out_file.write(self._MARSHAL_DECLARATION % {'type': self.new_type})
830    declared_types.add(self.new_type)
831
832  def OutputUnmarshalCall(
833      self, out_file, field):
834    """Write a call to Unmarshal function for Interface type to |out_file|.
835
836       Override TPMType OutputUnmarshalCall because when an Interface type has
837       a conditionally valid value, a BOOL value (|conditional_valid|) is passed
838       as a parameter.
839
840    Args:
841      out_file: The output file.
842      field: A Field object representing an element of this interface.
843    """
844    if self.conditional_value:
845      out_file.write(
846          self._CONDITIONAL_UNMARSHAL_CALL % {'type': field.field_type,
847                                              'name': field.field_name,
848                                              'flag': field.conditional_value})
849    else:
850      out_file.write(self._UNMARSHAL_CALL % {'type': field.field_type,
851                                             'name': field.field_name})
852
853
854class Structure(TPMType):
855  """Represents a TPM structure.
856
857  Attributes:
858    name: The name of the structure.
859    fields: A list of Field objects representing struct fields.
860    upper_bounds: A dictionary of (name, val) tuples mapping name to max val.
861    lower_bounds: A dictionary of (name, val) tuples mapping name to min val.
862    size_check: Set if TPM2B structure must be size checked (triggered by size=)
863    valid_tag_values: A list of values field tag is allowed to take.
864    error_code: The return code to be returned if an error occurs
865  """
866  _STRUCTURE_MARSHAL_START = """
867UINT16 %(name)s_Marshal(
868    %(name)s *source,
869    BYTE **buffer,
870    INT32 *size) {
871  UINT16 total_size = 0;"""
872  _STRUCTURE_UNMARSHAL_START = """
873TPM_RC %(name)s_Unmarshal(
874    %(name)s *target,
875    BYTE **buffer,
876    INT32 *size) {
877  TPM_RC result;"""
878  _MARSHAL_END = '\n  return total_size;\n}\n'
879  _SETUP_ARRAY_FIELD = '\n  INT32 i;'
880  _CHECK_SIZE_START = """
881  UINT32 start_size = *size;
882  UINT32 struct_size;"""
883  _CHECK_SIZE_END = """
884  struct_size = start_size - *size - sizeof(target->t.size);
885  if (struct_size != target->t.size) {
886    return TPM_RC_SIZE;
887  }"""
888  _TPM2B_ZERO_SIZE = """
889  if (target->t.size == 0) {
890    return %(return_value)s;
891  }"""
892  _CHECK_BOUND = """
893  if (target->%(name)s %(operator)s %(bound_value)s) {
894    return %(error_code)s;
895  }"""
896  _FIX_SIZE_FIELD = """
897  {
898    BYTE *size_location = *buffer - total_size;
899    INT32 size_field_size = sizeof(%(size_field_type)s);
900    UINT16 payload_size = total_size - (UINT16)size_field_size;
901    %(size_field_type)s_Marshal(&payload_size,
902      &size_location, &size_field_size);
903  }"""
904
905  def __init__(self, name):
906    """Initializes a Structure instance.
907
908    Initially the instance will have no fields, upper_bounds, lower_bounds, or
909    valid_tag_values. Those can be added with AddField(), AddUpperBound(),
910    AddLowerBound(), and AddTagVal() methods.
911
912    Args:
913      name: The name of the structure.
914    """
915    super(Structure, self).__init__()
916    self.name = name
917    self.fields = []
918    self.upper_bounds = {}
919    self.lower_bounds = {}
920    self.size_check = False
921    self.valid_tag_values = []
922    self.error_code = 'TPM_RC_VALUE'
923
924  def AddField(self, field):
925    """Adds a field to fields attribute in Structure.
926
927    Args:
928      field: Instance of Field
929    """
930    self.fields.append(field)
931
932  def AddUpperBound(self, field_name, value):
933    """Adds an upper bound for a field.
934
935    Args:
936       field_name: Name of field with bound.
937       value: Value of upper bound.
938    """
939    if _IsTPM2B(self.name):
940      field_name = 't.' + field_name
941    self.upper_bounds[field_name] = value
942
943  def AddLowerBound(self, field_name, value):
944    """Adds a lower bound for a field.
945
946    Args:
947       field_name: Name of field with bound.
948       value: Value of lower bound.
949    """
950    if _IsTPM2B(self.name):
951      field_name = 't.' + field_name
952    self.lower_bounds[field_name] = value
953
954  def _AddTagValue(self, value):
955    """Adds a valid value for tag field.
956
957    Args:
958       value: Valid value for tag field.
959    """
960    self.valid_tag_values.append(value)
961
962  def _GetFieldTypes(self):
963    """Creates a set which holds all current field types.
964
965    Returns:
966      A set of field types.
967    """
968    return set([field.field_type for field in self.fields])
969
970  def OutputMarshalImpl(self, out_file, marshalled_types, typemap):
971    """Writes marshal implementations for Structure to |out_file|.
972
973    Args:
974      out_file: The output file.
975      marshalled_types: A set of types for which marshal and unmarshal functions
976          have already been generated.
977      typemap: A dict mapping type names to the corresponding object.
978    """
979    if self.name in marshalled_types:
980      return
981
982    # Make sure any dependencies already have marshal functions defined.
983    for field_type in self._GetFieldTypes():
984      if field_type not in marshalled_types:
985        typemap[field_type].OutputMarshalImpl(
986            out_file, marshalled_types, typemap)
987        marshalled_types.add(field_type)
988
989    out_file.write(self._STRUCTURE_MARSHAL_START % {'name': self.name})
990    # If any field is an array, create local variable INT32 i.
991    for field in self.fields:
992      if field.array_size:
993        out_file.write(self._SETUP_ARRAY_FIELD)
994        break
995    for field in self.fields:
996      # Each TPM2B is a union of two sized buffers, one which is type specific
997      # (the 't' element) and the other is a generic value (the 'b' element).
998      # For this reason a 't.' is prepended for fields in a TPM2B type. See
999      # section 9.11.6 in TCG TPM2.0 Library Specification, Part 2: Structures
1000      # for more details.
1001      if _IsTPM2B(self.name):
1002        field.field_name = 't.' + field.field_name
1003        if field.run_time_size:
1004          field.run_time_size = 't.' + field.run_time_size
1005      field.OutputMarshal(out_file, typemap)
1006    if self.size_check:
1007      out_file.write(self._FIX_SIZE_FIELD % {'size_field_type': self.fields[0].field_type})
1008    out_file.write(self._MARSHAL_END)
1009
1010    out_file.write(self._STRUCTURE_UNMARSHAL_START % {'name': self.name})
1011    if self.size_check:
1012      out_file.write(self._CHECK_SIZE_START)
1013    # If any field is an array, create local variable INT32 i.
1014    for field in self.fields:
1015      if field.array_size:
1016        out_file.write(self._SETUP_ARRAY_FIELD)
1017        break
1018    for field in self.fields:
1019      field.OutputUnmarshal(out_file, typemap)
1020      return_value = self.error_code
1021      if field.field_name == 't.size' and self.size_check:
1022        out_file.write(self._TPM2B_ZERO_SIZE % {'return_value': 'TPM_RC_SIZE'})
1023      if field.field_name == 't.size' and not self.size_check:
1024        out_file.write(
1025            self._TPM2B_ZERO_SIZE % {'return_value': 'TPM_RC_SUCCESS'})
1026      if field.field_name in self.upper_bounds:
1027        if (field.field_name == 'count' or
1028            field.field_name == 't.size' or
1029            field.field_name == 'size'):
1030          return_value = 'TPM_RC_SIZE'
1031        out_file.write(self._CHECK_BOUND %
1032                       {'name': field.field_name,
1033                        'operator': '>',
1034                        'bound_value': self.upper_bounds[field.field_name],
1035                        'error_code': return_value})
1036      if field.field_name in self.lower_bounds:
1037        if (field.field_name == 'count' or
1038            field.field_name == 't.size' or
1039            field.field_name == 'size'):
1040          return_value = 'TPM_RC_SIZE'
1041        out_file.write(self._CHECK_BOUND %
1042                       {'name': field.field_name,
1043                        'operator': '<',
1044                        'bound_value': self.lower_bounds[field.field_name],
1045                        'error_code': return_value})
1046      if field.field_name == 'tag' and self.valid_tag_values:
1047        out_file.write(self._VALUE_START_SWITCH % {'name': 'target->tag'})
1048        for value in self.valid_tag_values:
1049          out_file.write(self._VALUE_CASE % {'value': value})
1050        out_file.write(self._VALUE_END_SWITCH % {'error_code': 'TPM_RC_TAG'})
1051    if self.size_check:
1052      out_file.write(self._CHECK_SIZE_END)
1053    if not self.fields:
1054      # The spec includes a definition of an empty structure, as a side effect
1055      # the marshaling/unmarshaling functions become empty, the compiler
1056      # warning is suppressed by the below statement.
1057      out_file.write('  (void)result;\n')
1058    out_file.write(self._UNMARSHAL_END)
1059
1060    marshalled_types.add(self.name)
1061
1062  def OutputMarshalDecl(self, out_file, declared_types, _):
1063    """Writes marshal declarations for Structure to |out_file|.
1064
1065    Args:
1066      out_file: The output file.
1067      declared_types: A set of types for which marshal and unmarshal function
1068          declarations have already been generated.
1069    """
1070    self._OutputStructOrUnionMarshalDecl(out_file, declared_types)
1071
1072
1073class Union(TPMType):
1074  """Represents a TPM union.
1075
1076  Attributes:
1077    name: The name of the union.
1078    fields: A list of Field objects representing union fields.
1079  """
1080
1081  _UNION_MARSHAL_START = """
1082UINT16 %(name)s_Marshal(
1083    %(name)s *source,
1084    BYTE **buffer,
1085    INT32 *size,
1086    UINT32 selector) {
1087  %(array_extras)s
1088  switch(selector) {"""
1089  _UNION_UNMARSHAL_START = """
1090TPM_RC %(name)s_Unmarshal(
1091    %(name)s *target,
1092    BYTE **buffer,
1093    INT32 *size,
1094    UINT32 selector) {
1095  switch(selector) {"""
1096  _MARSHAL_END = '\n  }\n  return 0;\n}\n'
1097  _UNMARSHAL_END = '\n  }\n  return TPM_RC_SELECTOR;\n}\n'
1098  _MARSHAL_DECLARATION = """
1099UINT16 %(type)s_Marshal(
1100    %(type)s *source,
1101    BYTE **buffer,
1102    INT32 *size,
1103    UINT32 selector);
1104
1105TPM_RC %(type)s_Unmarshal(
1106    %(type)s *target,
1107    BYTE **buffer,
1108    INT32 *size,
1109    UINT32 selector);
1110"""
1111  _CASE_SELECTOR = """
1112    case %(selector)s:"""
1113  _MARSHAL_EMPTY = """
1114      return 0;"""
1115  _UNMARSHAL_EMPTY = """
1116      return TPM_RC_SUCCESS;"""
1117  _MARSHAL_FIELD = """
1118      return %(type)s_Marshal(
1119          (%(type)s*)&source->%(name)s, buffer, size);"""
1120  _UNMARSHAL_FIELD = """
1121      return %(type)s_Unmarshal(
1122          (%(type)s*)&target->%(name)s, buffer, size);"""
1123  _SETUP_MARSHAL_FIELD_ARRAY = """
1124    INT32 i;
1125    UINT16 total_size = 0;"""
1126  _SETUP_UNMARSHAL_FIELD_ARRAY = """
1127    INT32 i;
1128    TPM_RC result = TPM_RC_SUCCESS;"""
1129  _MARSHAL_FIELD_ARRAY = """
1130    for (i = 0; i < %(array_length)s; ++i) {
1131      total_size += %(type)s_Marshal(
1132          &source->%(name)s[i], buffer, size);
1133    }
1134    return total_size;"""
1135  _UNMARSHAL_FIELD_ARRAY = """
1136    for (i = 0; i < %(array_length)s; ++i) {
1137      result = %(type)s_Unmarshal(
1138          &target->%(name)s[i], buffer, size);
1139      if (result != TPM_RC_SUCCESS) {
1140        return result;
1141      }
1142    }
1143    return TPM_RC_SUCCESS;"""
1144  _UNMARSHAL_FIELD_CONDITIONAL = """
1145    return %(type)s_Unmarshal(
1146        &target->%(name)s, buffer, size, FALSE);"""
1147  _UNION_MARSHAL_CALL = """
1148  total_size += %(type)s_Marshal(
1149      &source->%(name)s, buffer, size, source->%(selector)s);"""
1150  _UNION_UNMARSHAL_CALL = """
1151  result = %(type)s_Unmarshal(
1152      &target->%(name)s, buffer, size, target->%(selector)s);
1153  if (result != TPM_RC_SUCCESS) {
1154    return result;
1155  }"""
1156  _IFDEF = '\n#ifdef %(type)s'
1157  _ENDIF = '\n#endif'
1158  _IFDEF_TYPE_RE = re.compile(r'^TPM_(ALG|CC).*')
1159
1160  def __init__(self, name):
1161    """Initializes a Union instance.
1162
1163    Initially the instance will have no fields. Fields are added with the
1164    AddField() method.
1165
1166    Args:
1167      name: The name of the structure.
1168    """
1169    super(Union, self).__init__()
1170    self.name = name
1171    self.fields = []
1172
1173  def _NeedsIfdef(self, selector):
1174    """Returns True if selector is a type which needs ifdef enclosing."""
1175    return self._IFDEF_TYPE_RE.search(selector)
1176
1177  def AddField(self, field):
1178    """Adds a field to fields attribute in Union.
1179
1180    Args:
1181      field: instance of Field
1182    """
1183    # xor is a C++ keyword and must be fixed.
1184    if field.field_name == 'xor':
1185      field.field_name = 'xor_'
1186    self.fields.append(field)
1187
1188  def _OutputMarshalField(
1189      self, out_file, field_type, field_name, array_length):
1190    """Write a call to marshal a field in this union.
1191
1192    Args:
1193      out_file: The output file.
1194      field_type: The type of field.
1195      field_name: The name of the field.
1196      array_length: Variable indicating length of array, None if field is not
1197          an array.
1198    """
1199    if array_length:
1200      out_file.write(self._MARSHAL_FIELD_ARRAY % {'type': field_type,
1201                                                  'name': field_name,
1202                                                  'array_length': array_length})
1203    else:
1204      out_file.write(self._MARSHAL_FIELD % {'type': field_type,
1205                                            'name': field_name})
1206
1207  def _OutputUnmarshalField(
1208      self, out_file, field_type, field_name, array_length, typemap):
1209    """Write a call to unmarshal a field in this union.
1210
1211    Args:
1212      out_file: The output file object.
1213      field_type: The type of field.
1214      field_name: The name of the field.
1215      array_length: Variable indicating length of array, None if field is not
1216          an array.
1217      typemap: A dict mapping type names to the corresponding object.
1218    """
1219    if array_length:
1220      out_file.write(
1221          self._UNMARSHAL_FIELD_ARRAY % {'type': field_type,
1222                                         'name': field_name,
1223                                         'array_length': array_length})
1224    elif typemap[field_type].HasConditional():
1225      out_file.write(
1226          self._UNMARSHAL_FIELD_CONDITIONAL % {'type': field_type,
1227                                               'name': field_name})
1228    else:
1229      out_file.write(self._UNMARSHAL_FIELD % {'type': field_type,
1230                                              'name': field_name})
1231
1232  def OutputMarshalImpl(self, out_file, marshalled_types, typemap):
1233    """Writes marshal implementations for Union to |out_file|.
1234
1235    Args:
1236      out_file: The output file.
1237      marshalled_types: A set of types for which marshal and unmarshal functions
1238          have already been generated.
1239      typemap: A dict mapping type names to the corresponding object.
1240    """
1241    if (self.name in marshalled_types or
1242        self.name == 'TPMU_NAME' or
1243        self.name == 'TPMU_ENCRYPTED_SECRET' or
1244        not self.fields):
1245      return
1246
1247    field_types = {f.field_name: f.field_type for f in self.fields}
1248    array_lengths = {}
1249    for f in self.fields:
1250      if f.array_size:
1251        array_lengths[f.field_name] = f.array_size
1252      else:
1253        array_lengths[f.field_name] = None
1254
1255    # Make sure any dependencies already have marshal functions defined.
1256    for field_type in field_types.itervalues():
1257      if field_type not in marshalled_types:
1258        typemap[field_type].OutputMarshalImpl(
1259            out_file, marshalled_types, typemap)
1260        marshalled_types.add(field_type)
1261    if self.fields[0].array_size:
1262      array_extras = self._SETUP_MARSHAL_FIELD_ARRAY
1263    else:
1264      array_extras = ''
1265    out_file.write(self._UNION_MARSHAL_START % {'name': self.name,
1266                                                'array_extras': array_extras})
1267    # Set up variables if Union is an array type.
1268    for field in self.fields:
1269      selector = field.selector_value
1270      if not selector:
1271        continue
1272      field_name = field.field_name
1273      if self._NeedsIfdef(selector):
1274        out_file.write(self._IFDEF % {'type': selector})
1275      out_file.write(self._CASE_SELECTOR % {'selector': selector})
1276      # Selector is not associated with a name, so no marshaling occurs.
1277      if not field_name:
1278        out_file.write(self._MARSHAL_EMPTY)
1279        if self._NeedsIfdef(selector):
1280          out_file.write(self._ENDIF)
1281        continue
1282      field_type = field_types[field_name]
1283      array_length = array_lengths[field_name]
1284      self._OutputMarshalField(out_file, field_type, field_name, array_length)
1285      if self._NeedsIfdef(selector):
1286        out_file.write(self._ENDIF)
1287    out_file.write(self._MARSHAL_END)
1288    out_file.write(self._UNION_UNMARSHAL_START % {'name': self.name})
1289    # Set up variables if Union is an array type.
1290    if self.fields[0].array_size:
1291      out_file.write(self._SETUP_UNMARSHAL_FIELD_ARRAY)
1292    for field in self.fields:
1293      selector = field.selector_value
1294      if not selector:
1295        continue
1296      field_name = field.field_name
1297      if self._NeedsIfdef(selector):
1298        out_file.write(self._IFDEF % {'type': selector})
1299      out_file.write(self._CASE_SELECTOR % {'selector': selector})
1300      # Selector is not associated with a name, so no unmarshaling occurs.
1301      if not field_name:
1302        out_file.write(self._UNMARSHAL_EMPTY)
1303        if self._NeedsIfdef(selector):
1304          out_file.write(self._ENDIF)
1305        continue
1306      field_type = field_types[field_name]
1307      array_length = array_lengths[field_name]
1308      self._OutputUnmarshalField(
1309          out_file, field_type, field_name, array_length, typemap)
1310      if self._NeedsIfdef(selector):
1311        out_file.write(self._ENDIF)
1312    out_file.write(self._UNMARSHAL_END)
1313    marshalled_types.add(self.name)
1314
1315  def OutputMarshalDecl(self, out_file, declared_types, _):
1316    """Writes marshal declarations for Union to |out_file|.
1317
1318    Args:
1319      out_file: The output file.
1320      declared_types: A set of types for which marshal and unmarshal function
1321          declarations have already been generated.
1322    """
1323    self._OutputStructOrUnionMarshalDecl(out_file, declared_types)
1324
1325  def OutputMarshalCall(self, out_file, field):
1326    """Write a call to marshal function for Union type to |out_file|.
1327
1328       Override TPMType OutputMarshalCall to pass in selector value.
1329
1330    Args:
1331      out_file: The output file.
1332      field: A Field object representing a member of this union
1333    """
1334    out_file.write(self._UNION_MARSHAL_CALL %
1335                   {'type': field.field_type,
1336                    'name': field.field_name,
1337                    'selector': field.selector_value})
1338
1339  def OutputUnmarshalCall(self, out_file, field):
1340    """Write a call to unmarshal function for Union type to |out_file|.
1341
1342       Override TPMType OutputUnmashalCall to pass in selector value.
1343
1344    Args:
1345      out_file: The output file.
1346      field: A Field object representing a member of this union
1347    """
1348    out_file.write(self._UNION_UNMARSHAL_CALL %
1349                   {'type': field.field_type,
1350                    'name': field.field_name,
1351                    'selector': field.selector_value})
1352
1353
1354def GenerateHeader(typemap):
1355  """Generates a header file with declarations for all given generator objects.
1356
1357  Args:
1358    typemap: A dict mapping type names to the corresponding object.
1359  """
1360  out_file = open(_OUTPUT_FILE_H, 'w')
1361  out_file.write(COPYRIGHT_HEADER)
1362  guard_name = 'TPM2_%s_' % _OUTPUT_FILE_H.upper().replace('.', '_')
1363  out_file.write(HEADER_FILE_GUARD_HEADER % {'name': guard_name})
1364  out_file.write(_HEADER_FILE_INCLUDES)
1365  # These types are built-in or defined by <stdint.h>; they serve as base cases
1366  # when defining type dependencies.
1367  declared_types = set(_BASIC_TYPES)
1368  # Generate serialize / parse function declarations.
1369  for basic_type in _BASIC_TYPES:
1370    out_file.write(_STANDARD_MARSHAL_DECLARATION % {'type': basic_type})
1371  for tpm_type in [typemap[x] for x in sorted(typemap.keys())]:
1372    tpm_type.OutputMarshalDecl(out_file, declared_types, typemap)
1373  out_file.write(HEADER_FILE_GUARD_FOOTER % {'name': guard_name})
1374  out_file.close()
1375  call(['clang-format', '-i', '-style=Chromium', 'tpm_generated.h'])
1376
1377
1378def GenerateImplementation(typemap):
1379  """Generates implementation code for each type.
1380
1381  Args:
1382    typemap: A dict mapping string type names to the corresponding object.
1383  """
1384  out_file = open(_OUTPUT_FILE_CC, 'w')
1385  out_file.write(COPYRIGHT_HEADER)
1386  out_file.write(_IMPLEMENTATION_FILE_INCLUDES)
1387  marshalled_types = set(_BASIC_TYPES)
1388  for basic_type in _BASIC_TYPES:
1389    out_file.write(_MARSHAL_BASIC_TYPE % {'type': basic_type})
1390  for tpm_type in [typemap[x] for x in sorted(typemap.keys())]:
1391    tpm_type.OutputMarshalImpl(out_file, marshalled_types, typemap)
1392  out_file.close()
1393  call(['clang-format', '-i', '-style=Chromium', 'tpm_generated.c'])
1394