1#!/usr/bin/python2
2
3#
4# Copyright (C) 2014 The Android Open Source Project
5#
6# Licensed under the Apache License, Version 2.0 (the "License");
7# you may not use this file except in compliance with the License.
8# You may obtain a copy of the License at
9#
10#      http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17#
18
19"""A code generator for TPM 2.0 structures and commands.
20
21The generator takes as input a structures file as emitted by the
22extract_structures.sh script and a commands file as emitted by the
23extract_commands.sh script.  It outputs valid C++ into tpm_generated.{h,cc}.
24
25The input grammar is documented in the extract_* scripts. Sample input for
26structures looks like this:
27_BEGIN_TYPES
28_OLD_TYPE UINT32
29_NEW_TYPE TPM_HANDLE
30_END
31_BEGIN_CONSTANTS
32_CONSTANTS (UINT32) TPM_SPEC
33_TYPE UINT32
34_NAME TPM_SPEC_FAMILY
35_VALUE 0x322E3000
36_NAME TPM_SPEC_LEVEL
37_VALUE 00
38_END
39_BEGIN_STRUCTURES
40_STRUCTURE TPMS_TIME_INFO
41_TYPE UINT64
42_NAME time
43_TYPE TPMS_CLOCK_INFO
44_NAME clockInfo
45_END
46
47Sample input for commands looks like this:
48_BEGIN
49_INPUT_START TPM2_Startup
50_TYPE TPMI_ST_COMMAND_TAG
51_NAME tag
52_COMMENT TPM_ST_NO_SESSIONS
53_TYPE UINT32
54_NAME commandSize
55_TYPE TPM_CC
56_NAME commandCode
57_COMMENT TPM_CC_Startup {NV}
58_TYPE TPM_SU
59_NAME startupType
60_COMMENT TPM_SU_CLEAR or TPM_SU_STATE
61_OUTPUT_START TPM2_Startup
62_TYPE TPM_ST
63_NAME tag
64_COMMENT see clause 8
65_TYPE UINT32
66_NAME responseSize
67_TYPE TPM_RC
68_NAME responseCode
69_END
70"""
71
72from __future__ import print_function
73
74import argparse
75import re
76import subprocess
77
78import union_selectors
79
80_BASIC_TYPES = ['uint8_t', 'int8_t', 'int', 'uint16_t', 'int16_t',
81                'uint32_t', 'int32_t', 'uint64_t', 'int64_t']
82_OUTPUT_FILE_H = 'tpm_generated.h'
83_OUTPUT_FILE_CC = 'tpm_generated.cc'
84_COPYRIGHT_HEADER = (
85    '//\n'
86    '// Copyright (C) 2015 The Android Open Source Project\n'
87    '//\n'
88    '// Licensed under the Apache License, Version 2.0 (the "License");\n'
89    '// you may not use this file except in compliance with the License.\n'
90    '// You may obtain a copy of the License at\n'
91    '//\n'
92    '//      http://www.apache.org/licenses/LICENSE-2.0\n'
93    '//\n'
94    '// Unless required by applicable law or agreed to in writing, software\n'
95    '// distributed under the License is distributed on an "AS IS" BASIS,\n'
96    '// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or '
97    'implied.\n'
98    '// See the License for the specific language governing permissions and\n'
99    '// limitations under the License.\n'
100    '//\n\n'
101    '// THIS CODE IS GENERATED - DO NOT MODIFY!\n')
102_HEADER_FILE_GUARD_HEADER = """
103#ifndef %(name)s
104#define %(name)s
105"""
106_HEADER_FILE_GUARD_FOOTER = """
107#endif  // %(name)s
108"""
109_HEADER_FILE_INCLUDES = """
110#include <string>
111
112#include <base/callback_forward.h>
113#include <base/macros.h>
114
115#include "trunks/trunks_export.h"
116"""
117_IMPLEMENTATION_FILE_INCLUDES = """
118#include <memory>
119#include <string>
120
121#include <base/bind.h>
122#include <base/callback.h>
123#include <base/logging.h>
124#include <base/macros.h>
125#include <base/stl_util.h>
126#include <base/strings/string_number_conversions.h>
127#include <base/sys_byteorder.h>
128#include <crypto/secure_hash.h>
129
130#include "trunks/authorization_delegate.h"
131#include "trunks/command_transceiver.h"
132#include "trunks/error_codes.h"
133
134"""
135_LOCAL_INCLUDE = """
136#include "trunks/%(filename)s"
137"""
138_NAMESPACE_BEGIN = """
139namespace trunks {
140"""
141_NAMESPACE_END = """
142}  // namespace trunks
143"""
144_FORWARD_DECLARATIONS = """
145class AuthorizationDelegate;
146class CommandTransceiver;
147"""
148_FUNCTION_DECLARATIONS = """
149TRUNKS_EXPORT size_t GetNumberOfRequestHandles(TPM_CC command_code);
150TRUNKS_EXPORT size_t GetNumberOfResponseHandles(TPM_CC command_code);
151"""
152_CLASS_BEGIN = """
153class TRUNKS_EXPORT Tpm {
154 public:
155  // Does not take ownership of |transceiver|.
156  explicit Tpm(CommandTransceiver* transceiver) : transceiver_(transceiver) {}
157  virtual ~Tpm() {}
158
159"""
160_CLASS_END = """
161 private:
162  CommandTransceiver* transceiver_;
163
164  DISALLOW_COPY_AND_ASSIGN(Tpm);
165};
166"""
167_SERIALIZE_BASIC_TYPE = """
168TPM_RC Serialize_%(type)s(const %(type)s& value, std::string* buffer) {
169  VLOG(3) << __func__;
170  %(type)s value_net = value;
171  switch (sizeof(%(type)s)) {
172    case 2:
173      value_net = base::HostToNet16(value);
174      break;
175    case 4:
176      value_net = base::HostToNet32(value);
177      break;
178    case 8:
179      value_net = base::HostToNet64(value);
180      break;
181    default:
182      break;
183  }
184  const char* value_bytes = reinterpret_cast<const char*>(&value_net);
185  buffer->append(value_bytes, sizeof(%(type)s));
186  return TPM_RC_SUCCESS;
187}
188
189TPM_RC Parse_%(type)s(
190    std::string* buffer,
191    %(type)s* value,
192    std::string* value_bytes) {
193  VLOG(3) << __func__;
194  if (buffer->size() < sizeof(%(type)s))
195    return TPM_RC_INSUFFICIENT;
196  %(type)s value_net = 0;
197  memcpy(&value_net, buffer->data(), sizeof(%(type)s));
198  switch (sizeof(%(type)s)) {
199    case 2:
200      *value = base::NetToHost16(value_net);
201      break;
202    case 4:
203      *value = base::NetToHost32(value_net);
204      break;
205    case 8:
206      *value = base::NetToHost64(value_net);
207      break;
208    default:
209      *value = value_net;
210  }
211  if (value_bytes) {
212    value_bytes->append(buffer->substr(0, sizeof(%(type)s)));
213  }
214  buffer->erase(0, sizeof(%(type)s));
215  return TPM_RC_SUCCESS;
216}
217"""
218_SERIALIZE_DECLARATION = """
219TRUNKS_EXPORT TPM_RC Serialize_%(type)s(
220    const %(type)s& value,
221    std::string* buffer);
222
223TRUNKS_EXPORT TPM_RC Parse_%(type)s(
224    std::string* buffer,
225    %(type)s* value,
226    std::string* value_bytes);
227"""
228
229_SIMPLE_TPM2B_HELPERS_DECLARATION = """
230TRUNKS_EXPORT %(type)s Make_%(type)s(
231    const std::string& bytes);
232TRUNKS_EXPORT std::string StringFrom_%(type)s(
233    const %(type)s& tpm2b);
234"""
235_COMPLEX_TPM2B_HELPERS_DECLARATION = """
236TRUNKS_EXPORT %(type)s Make_%(type)s(
237    const %(inner_type)s& inner);
238"""
239
240_HANDLE_COUNT_FUNCTION_START = """
241size_t GetNumberOf%(handle_type)sHandles(TPM_CC command_code) {
242  switch (command_code) {"""
243_HANDLE_COUNT_FUNCTION_CASE = """
244    case %(command_code)s: return %(handle_count)s;"""
245_HANDLE_COUNT_FUNCTION_END = """
246    default: LOG(WARNING) << "Unknown command code: " << command_code;
247  }
248  return 0;
249}
250"""
251
252def FixName(name):
253  """Fixes names to conform to Chromium style."""
254  # Handle names with array notation. E.g. 'myVar[10]' is grouped as 'myVar' and
255  # '[10]'.
256  match = re.search(r'([^\[]*)(\[.*\])*', name)
257  # Transform the name to Chromium style. E.g. 'myVarAgain' becomes
258  # 'my_var_again'.
259  fixed_name = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', match.group(1)).lower()
260  return fixed_name + match.group(2) if match.group(2) else fixed_name
261
262
263def IsTPM2B(name):
264  return name.startswith('TPM2B_')
265
266
267def GetCppBool(condition):
268  if condition:
269    return 'true'
270  return 'false'
271
272
273class Typedef(object):
274  """Represents a TPM typedef.
275
276  Attributes:
277    old_type: The existing type in a typedef statement.
278    new_type: The new type in a typedef statement.
279  """
280
281  _TYPEDEF = 'typedef %(old_type)s %(new_type)s;\n'
282  _SERIALIZE_FUNCTION = """
283TPM_RC Serialize_%(new)s(
284    const %(new)s& value,
285    std::string* buffer) {
286  VLOG(3) << __func__;
287  return Serialize_%(old)s(value, buffer);
288}
289"""
290  _PARSE_FUNCTION = """
291TPM_RC Parse_%(new)s(
292    std::string* buffer,
293    %(new)s* value,
294    std::string* value_bytes) {
295  VLOG(3) << __func__;
296  return Parse_%(old)s(buffer, value, value_bytes);
297}
298"""
299
300  def __init__(self, old_type, new_type):
301    """Initializes a Typedef instance.
302
303    Args:
304      old_type: The existing type in a typedef statement.
305      new_type: The new type in a typedef statement.
306    """
307    self.old_type = old_type
308    self.new_type = new_type
309
310  def OutputForward(self, out_file, defined_types, typemap):
311    """Writes a typedef definition to |out_file|.
312
313    Any outstanding dependencies will be forward declared. This method is the
314    same as Output() because forward declarations do not apply for typedefs.
315
316    Args:
317      out_file: The output file.
318      defined_types: A set of types for which definitions have already been
319          generated.
320      typemap: A dict mapping type names to the corresponding object.
321    """
322    self.Output(out_file, defined_types, typemap)
323
324  def Output(self, out_file, defined_types, typemap):
325    """Writes a typedef definition to |out_file|.
326
327    Any outstanding dependencies will be forward declared.
328
329    Args:
330      out_file: The output file.
331      defined_types: A set of types for which definitions have already been
332          generated.
333      typemap: A dict mapping type names to the corresponding object.
334    """
335    if self.new_type in defined_types:
336      return
337    # Make sure the dependency is already defined.
338    if self.old_type not in defined_types:
339      typemap[self.old_type].OutputForward(out_file, defined_types, typemap)
340    out_file.write(self._TYPEDEF % {'old_type': self.old_type,
341                                    'new_type': self.new_type})
342    defined_types.add(self.new_type)
343
344  def OutputSerialize(self, out_file, serialized_types, typemap):
345    """Writes a serialize and parse function for the typedef to |out_file|.
346
347    Args:
348      out_file: The output file.
349      serialized_types: A set of types for which serialize and parse functions
350        have already been generated.
351      typemap: A dict mapping type names to the corresponding object.
352    """
353    if self.new_type in serialized_types:
354      return
355    if self.old_type not in serialized_types:
356      typemap[self.old_type].OutputSerialize(out_file, serialized_types,
357                                             typemap)
358    out_file.write(self._SERIALIZE_FUNCTION % {'old': self.old_type,
359                                               'new': self.new_type})
360    out_file.write(self._PARSE_FUNCTION % {'old': self.old_type,
361                                           'new': self.new_type})
362    serialized_types.add(self.new_type)
363
364
365class Constant(object):
366  """Represents a TPM constant.
367
368  Attributes:
369    const_type: The type of the constant (e.g. 'int').
370    name: The name of the constant (e.g. 'kMyConstant').
371    value: The value of the constant (e.g. '7').
372  """
373
374  _CONSTANT = 'constexpr %(type)s %(name)s = %(value)s;\n'
375
376  def __init__(self, const_type, name, value):
377    """Initializes a Constant instance.
378
379    Args:
380      const_type: The type of the constant (e.g. 'int').
381      name: The name of the constant (e.g. 'kMyConstant').
382      value: The value of the constant (e.g. '7').
383    """
384    self.const_type = const_type
385    self.name = name
386    self.value = value
387
388  def Output(self, out_file, defined_types, typemap):
389    """Writes a constant definition to |out_file|.
390
391    Any outstanding dependencies will be forward declared.
392
393    Args:
394      out_file: The output file.
395      defined_types: A set of types for which definitions have already been
396          generated.
397      typemap: A dict mapping type names to the corresponding object.
398    """
399    # Make sure the dependency is already defined.
400    if self.const_type not in defined_types:
401      typemap[self.const_type].OutputForward(out_file, defined_types, typemap)
402    out_file.write(self._CONSTANT % {'type': self.const_type,
403                                     'name': self.name,
404                                     'value': self.value})
405
406
407class Structure(object):
408  """Represents a TPM structure or union.
409
410  Attributes:
411    name: The name of the structure.
412    is_union: A boolean indicating whether this is a union.
413    fields: A list of (type, name) tuples representing the struct fields.
414    depends_on: A list of strings for types this struct depends on other than
415        field types. See AddDependency() for more details.
416  """
417
418  _STRUCTURE = 'struct %(name)s {\n'
419  _STRUCTURE_FORWARD = 'struct %(name)s;\n'
420  _UNION = 'union %(name)s {\n'
421  _UNION_FORWARD = 'union %(name)s;\n'
422  _STRUCTURE_END = '};\n\n'
423  _STRUCTURE_FIELD = '  %(type)s %(name)s;\n'
424  _SERIALIZE_FUNCTION_START = """
425TPM_RC Serialize_%(type)s(
426    const %(type)s& value,
427    std::string* buffer) {
428  TPM_RC result = TPM_RC_SUCCESS;
429  VLOG(3) << __func__;
430"""
431  _SERIALIZE_FIELD = """
432  result = Serialize_%(type)s(value.%(name)s, buffer);
433  if (result) {
434    return result;
435  }
436"""
437  _SERIALIZE_FIELD_ARRAY = """
438  if (arraysize(value.%(name)s) < value.%(count)s) {
439    return TPM_RC_INSUFFICIENT;
440  }
441  for (uint32_t i = 0; i < value.%(count)s; ++i) {
442    result = Serialize_%(type)s(value.%(name)s[i], buffer);
443    if (result) {
444      return result;
445    }
446  }
447"""
448  _SERIALIZE_FIELD_WITH_SELECTOR = """
449  result = Serialize_%(type)s(
450      value.%(name)s,
451      value.%(selector_name)s,
452      buffer);
453  if (result) {
454    return result;
455  }
456"""
457  _SERIALIZE_COMPLEX_TPM2B = """
458  std::string field_bytes;
459  result = Serialize_%(type)s(value.%(name)s, &field_bytes);
460  if (result) {
461    return result;
462  }
463  std::string size_bytes;
464  result = Serialize_UINT16(field_bytes.size(), &size_bytes);
465  if (result) {
466    return result;
467  }
468  buffer->append(size_bytes + field_bytes);
469"""
470  _PARSE_FUNCTION_START = """
471TPM_RC Parse_%(type)s(
472    std::string* buffer,
473    %(type)s* value,
474    std::string* value_bytes) {
475  TPM_RC result = TPM_RC_SUCCESS;
476  VLOG(3) << __func__;
477"""
478  _PARSE_FIELD = """
479  result = Parse_%(type)s(
480      buffer,
481      &value->%(name)s,
482      value_bytes);
483  if (result) {
484    return result;
485  }
486"""
487  _PARSE_FIELD_ARRAY = """
488  if (arraysize(value->%(name)s) < value->%(count)s) {
489    return TPM_RC_INSUFFICIENT;
490  }
491  for (uint32_t i = 0; i < value->%(count)s; ++i) {
492    result = Parse_%(type)s(
493        buffer,
494        &value->%(name)s[i],
495        value_bytes);
496    if (result) {
497      return result;
498    }
499  }
500"""
501  _PARSE_FIELD_WITH_SELECTOR = """
502  result = Parse_%(type)s(
503      buffer,
504      value->%(selector_name)s,
505      &value->%(name)s,
506      value_bytes);
507  if (result) {
508    return result;
509  }
510"""
511  _SERIALIZE_FUNCTION_END = '  return result;\n}\n'
512  _ARRAY_FIELD_RE = re.compile(r'(.*)\[(.*)\]')
513  _ARRAY_FIELD_SIZE_RE = re.compile(r'^(count|size)')
514  _UNION_TYPE_RE = re.compile(r'^TPMU_.*')
515  _SERIALIZE_UNION_FUNCTION_START = """
516TPM_RC Serialize_%(union_type)s(
517    const %(union_type)s& value,
518    %(selector_type)s selector,
519    std::string* buffer) {
520  TPM_RC result = TPM_RC_SUCCESS;
521  VLOG(3) << __func__;
522"""
523  _SERIALIZE_UNION_FIELD = """
524  if (selector == %(selector_value)s) {
525    result = Serialize_%(field_type)s(value.%(field_name)s, buffer);
526    if (result) {
527      return result;
528    }
529  }
530"""
531  _SERIALIZE_UNION_FIELD_ARRAY = """
532  if (selector == %(selector_value)s) {
533    if (arraysize(value.%(field_name)s) < %(count)s) {
534      return TPM_RC_INSUFFICIENT;
535    }
536    for (uint32_t i = 0; i < %(count)s; ++i) {
537      result = Serialize_%(field_type)s(value.%(field_name)s[i], buffer);
538      if (result) {
539        return result;
540      }
541    }
542  }
543"""
544  _PARSE_UNION_FUNCTION_START = """
545TPM_RC Parse_%(union_type)s(
546    std::string* buffer,
547    %(selector_type)s selector,
548    %(union_type)s* value,
549    std::string* value_bytes) {
550  TPM_RC result = TPM_RC_SUCCESS;
551  VLOG(3) << __func__;
552"""
553  _PARSE_UNION_FIELD = """
554  if (selector == %(selector_value)s) {
555    result = Parse_%(field_type)s(
556        buffer,
557        &value->%(field_name)s,
558        value_bytes);
559    if (result) {
560      return result;
561    }
562  }
563"""
564  _PARSE_UNION_FIELD_ARRAY = """
565  if (selector == %(selector_value)s) {
566    if (arraysize(value->%(field_name)s) < %(count)s) {
567      return TPM_RC_INSUFFICIENT;
568    }
569    for (uint32_t i = 0; i < %(count)s; ++i) {
570      result = Parse_%(field_type)s(
571          buffer,
572          &value->%(field_name)s[i],
573          value_bytes);
574      if (result) {
575        return result;
576      }
577    }
578  }
579"""
580  _EMPTY_UNION_CASE = """
581  if (selector == %(selector_value)s) {
582    // Do nothing.
583  }
584"""
585  _SIMPLE_TPM2B_HELPERS = """
586%(type)s Make_%(type)s(
587    const std::string& bytes) {
588  %(type)s tpm2b;
589  CHECK(bytes.size() <= sizeof(tpm2b.%(buffer_name)s));
590  memset(&tpm2b, 0, sizeof(%(type)s));
591  tpm2b.size = bytes.size();
592  memcpy(tpm2b.%(buffer_name)s, bytes.data(), bytes.size());
593  return tpm2b;
594}
595
596std::string StringFrom_%(type)s(
597    const %(type)s& tpm2b) {
598  const char* char_buffer = reinterpret_cast<const char*>(
599      tpm2b.%(buffer_name)s);
600  return std::string(char_buffer, tpm2b.size);
601}
602"""
603  _COMPLEX_TPM2B_HELPERS = """
604%(type)s Make_%(type)s(
605    const %(inner_type)s& inner) {
606  %(type)s tpm2b;
607  tpm2b.size = sizeof(%(inner_type)s);
608  tpm2b.%(inner_name)s = inner;
609  return tpm2b;
610}
611"""
612
613  def __init__(self, name, is_union):
614    """Initializes a Structure instance.
615
616    Initially the instance will have no fields and no dependencies. Those can be
617    added with the AddField() and AddDependency() methods.
618
619    Args:
620      name: The name of the structure.
621      is_union: A boolean indicating whether this is a union.
622    """
623    self.name = name
624    self.is_union = is_union
625    self.fields = []
626    self.depends_on = []
627    self._forwarded = False
628
629  def AddField(self, field_type, field_name):
630    """Adds a field for this struct.
631
632    Args:
633      field_type: The type of the field.
634      field_name: The name of the field.
635    """
636    self.fields.append((field_type, FixName(field_name)))
637
638  def AddDependency(self, required_type):
639    """Adds an explicit dependency on another type.
640
641    This is used in cases where there is an additional dependency other than the
642    field types, which are implicit dependencies.  For example, a field like
643    FIELD_TYPE value[sizeof(OTHER_TYPE)] would need OTHER_TYPE to be already
644    declared.
645
646    Args:
647      required_type: The type this structure depends on.
648    """
649    self.depends_on.append(required_type)
650
651  def IsSimpleTPM2B(self):
652    """Returns whether this struct is a TPM2B structure with raw bytes."""
653    return self.name.startswith('TPM2B_') and self.fields[1][0] == 'BYTE'
654
655  def IsComplexTPM2B(self):
656    """Returns whether this struct is a TPM2B structure with an inner struct."""
657    return self.name.startswith('TPM2B_') and self.fields[1][0] != 'BYTE'
658
659  def _GetFieldTypes(self):
660    """Creates a set which holds all current field types.
661
662    Returns:
663      A set of field types.
664    """
665    return set([field[0] for field in self.fields])
666
667  def OutputForward(self, out_file, unused_defined_types, unused_typemap):
668    """Writes a structure forward declaration to |out_file|.
669
670    This method needs to match the OutputForward method in other type classes
671    (e.g. Typedef) which is why the unused_* args exist.
672
673    Args:
674      out_file: The output file.
675      unused_defined_types: Not used.
676      unused_typemap: Not used.
677    """
678    if self._forwarded:
679      return
680    if self.is_union:
681      out_file.write(self._UNION_FORWARD % {'name': self.name})
682    else:
683      out_file.write(self._STRUCTURE_FORWARD % {'name': self.name})
684    self._forwarded = True
685
686  def Output(self, out_file, defined_types, typemap):
687    """Writes a structure definition to |out_file|.
688
689    Any outstanding dependencies will be defined.
690
691    Args:
692      out_file: The output file.
693      defined_types: A set of types for which definitions have already been
694        generated.
695      typemap: A dict mapping type names to the corresponding object.
696    """
697    if self.name in defined_types:
698      return
699    # Make sure any dependencies are already defined.
700    for field_type in self._GetFieldTypes():
701      if field_type not in defined_types:
702        typemap[field_type].Output(out_file, defined_types, typemap)
703    for required_type in self.depends_on:
704      if required_type not in defined_types:
705        typemap[required_type].Output(out_file, defined_types, typemap)
706    if self.is_union:
707      out_file.write(self._UNION % {'name': self.name})
708    else:
709      out_file.write(self._STRUCTURE % {'name': self.name})
710    for field in self.fields:
711      out_file.write(self._STRUCTURE_FIELD % {'type': field[0],
712                                              'name': field[1]})
713    out_file.write(self._STRUCTURE_END)
714    defined_types.add(self.name)
715
716  def OutputSerialize(self, out_file, serialized_types, typemap):
717    """Writes serialize and parse functions for a structure to |out_file|.
718
719    Args:
720      out_file: The output file.
721      serialized_types: A set of types for which serialize and parse functions
722        have already been generated.  This type name of this structure will be
723        added on success.
724      typemap: A dict mapping type names to the corresponding object.
725    """
726    if (self.name in serialized_types or
727        self.name == 'TPMU_NAME' or
728        self.name == 'TPMU_ENCRYPTED_SECRET'):
729      return
730    # Make sure any dependencies already have serialize functions defined.
731    for field_type in self._GetFieldTypes():
732      if field_type not in serialized_types:
733        typemap[field_type].OutputSerialize(out_file, serialized_types, typemap)
734    if self.is_union:
735      self._OutputUnionSerialize(out_file)
736      serialized_types.add(self.name)
737      return
738    out_file.write(self._SERIALIZE_FUNCTION_START % {'type': self.name})
739    if self.IsComplexTPM2B():
740      field_type = self.fields[1][0]
741      field_name = self.fields[1][1]
742      out_file.write(self._SERIALIZE_COMPLEX_TPM2B % {'type': field_type,
743                                                      'name': field_name})
744    else:
745      for field in self.fields:
746        if self._ARRAY_FIELD_RE.search(field[1]):
747          self._OutputArrayField(out_file, field, self._SERIALIZE_FIELD_ARRAY)
748        elif self._UNION_TYPE_RE.search(field[0]):
749          self._OutputUnionField(out_file, field,
750                                 self._SERIALIZE_FIELD_WITH_SELECTOR)
751        else:
752          out_file.write(self._SERIALIZE_FIELD % {'type': field[0],
753                                                  'name': field[1]})
754    out_file.write(self._SERIALIZE_FUNCTION_END)
755    out_file.write(self._PARSE_FUNCTION_START % {'type': self.name})
756    for field in self.fields:
757      if self._ARRAY_FIELD_RE.search(field[1]):
758        self._OutputArrayField(out_file, field, self._PARSE_FIELD_ARRAY)
759      elif self._UNION_TYPE_RE.search(field[0]):
760        self._OutputUnionField(out_file, field, self._PARSE_FIELD_WITH_SELECTOR)
761      else:
762        out_file.write(self._PARSE_FIELD % {'type': field[0],
763                                            'name': field[1]})
764    out_file.write(self._SERIALIZE_FUNCTION_END)
765    # If this is a TPM2B structure throw in a few convenience functions.
766    if self.IsSimpleTPM2B():
767      field_name = self._ARRAY_FIELD_RE.search(self.fields[1][1]).group(1)
768      out_file.write(self._SIMPLE_TPM2B_HELPERS % {'type': self.name,
769                                                   'buffer_name': field_name})
770    elif self.IsComplexTPM2B():
771      field_type = self.fields[1][0]
772      field_name = self.fields[1][1]
773      out_file.write(self._COMPLEX_TPM2B_HELPERS % {'type': self.name,
774                                                    'inner_type': field_type,
775                                                    'inner_name': field_name})
776    serialized_types.add(self.name)
777
778  def _OutputUnionSerialize(self, out_file):
779    """Writes serialize and parse functions for a union to |out_file|.
780
781    This is more complex than the struct case because only one field of the
782    union is serialized / parsed based on the value of a selector.  Arrays are
783    also handled differently: the full size of the array is serialized instead
784    of looking for a field which specifies the count.
785
786    Args:
787      out_file: The output file
788    """
789    selector_type = union_selectors.GetUnionSelectorType(self.name)
790    selector_values = union_selectors.GetUnionSelectorValues(self.name)
791    field_types = {f[1]: f[0] for f in self.fields}
792    out_file.write(self._SERIALIZE_UNION_FUNCTION_START %
793                   {'union_type': self.name, 'selector_type': selector_type})
794    for selector in selector_values:
795      field_name = FixName(union_selectors.GetUnionSelectorField(self.name,
796                                                                 selector))
797      if not field_name:
798        out_file.write(self._EMPTY_UNION_CASE % {'selector_value': selector})
799        continue
800      field_type = field_types[field_name]
801      array_match = self._ARRAY_FIELD_RE.search(field_name)
802      if array_match:
803        field_name = array_match.group(1)
804        count = array_match.group(2)
805        out_file.write(self._SERIALIZE_UNION_FIELD_ARRAY %
806                       {'selector_value': selector,
807                        'count': count,
808                        'field_type': field_type,
809                        'field_name': field_name})
810      else:
811        out_file.write(self._SERIALIZE_UNION_FIELD %
812                       {'selector_value': selector,
813                        'field_type': field_type,
814                        'field_name': field_name})
815    out_file.write(self._SERIALIZE_FUNCTION_END)
816    out_file.write(self._PARSE_UNION_FUNCTION_START %
817                   {'union_type': self.name, 'selector_type': selector_type})
818    for selector in selector_values:
819      field_name = FixName(union_selectors.GetUnionSelectorField(self.name,
820                                                                 selector))
821      if not field_name:
822        out_file.write(self._EMPTY_UNION_CASE % {'selector_value': selector})
823        continue
824      field_type = field_types[field_name]
825      array_match = self._ARRAY_FIELD_RE.search(field_name)
826      if array_match:
827        field_name = array_match.group(1)
828        count = array_match.group(2)
829        out_file.write(self._PARSE_UNION_FIELD_ARRAY %
830                       {'selector_value': selector,
831                        'count': count,
832                        'field_type': field_type,
833                        'field_name': field_name})
834      else:
835        out_file.write(self._PARSE_UNION_FIELD %
836                       {'selector_value': selector,
837                        'field_type': field_type,
838                        'field_name': field_name})
839    out_file.write(self._SERIALIZE_FUNCTION_END)
840
841  def _OutputUnionField(self, out_file, field, code_format):
842    """Writes serialize / parse code for a union field.
843
844    In this case |self| may not necessarily represent a union but |field| does.
845    This requires that a field of an acceptable selector type appear somewhere
846    in the struct.  The value of this field is used as the selector value when
847    calling the serialize / parse function for the union.
848
849    Args:
850      out_file: The output file.
851      field: The union field to be processed as a (type, name) tuple.
852      code_format: Must be (_SERIALIZE|_PARSE)_FIELD_WITH_SELECTOR
853    """
854    selector_types = union_selectors.GetUnionSelectorTypes(field[0])
855    selector_name = ''
856    for tmp in self.fields:
857      if tmp[0] in selector_types:
858        selector_name = tmp[1]
859        break
860    assert selector_name, 'Missing selector for %s in %s!' % (field[1],
861                                                              self.name)
862    out_file.write(code_format % {'type': field[0],
863                                  'selector_name': selector_name,
864                                  'name': field[1]})
865
866  def _OutputArrayField(self, out_file, field, code_format):
867    """Writes serialize / parse code for an array field.
868
869    The allocated size of the array is ignored and a field which holds the
870    actual count of items in the array must exist.  Only the number of items
871    represented by the value of that count field are serialized / parsed.
872
873    Args:
874      out_file: The output file.
875      field: The array field to be processed as a (type, name) tuple.
876      code_format: Must be (_SERIALIZE|_PARSE)_FIELD_ARRAY
877    """
878    field_name = self._ARRAY_FIELD_RE.search(field[1]).group(1)
879    for count_field in self.fields:
880      assert count_field != field, ('Missing count field for %s in %s!' %
881                                    (field[1], self.name))
882      if self._ARRAY_FIELD_SIZE_RE.search(count_field[1]):
883        out_file.write(code_format % {'count': count_field[1],
884                                      'type': field[0],
885                                      'name': field_name})
886        break
887
888
889class Define(object):
890  """Represents a preprocessor define.
891
892  Attributes:
893    name: The name being defined.
894    value: The value being assigned to the name.
895  """
896
897  _DEFINE = '#if !defined(%(name)s)\n#define %(name)s %(value)s\n#endif\n'
898
899  def __init__(self, name, value):
900    """Initializes a Define instance.
901
902    Args:
903      name: The name being defined.
904      value: The value being assigned to the name.
905    """
906    self.name = name
907    # Prepend 'trunks::' to types.
908    self.value = re.sub(r'(TPM.?_|U?INT[0-9]{2})', r'trunks::\1', value)
909
910  def Output(self, out_file):
911    """Writes a preprocessor define to |out_file|.
912
913    Args:
914      out_file: The output file.
915    """
916    out_file.write(self._DEFINE % {'name': self.name, 'value': self.value})
917
918
919class StructureParser(object):
920  """Structure definition parser.
921
922  The input text file is extracted from the PDF file containing the TPM
923  structures specification from the Trusted Computing Group. The syntax
924  of the text file is defined by extract_structures.sh.
925
926  - Parses typedefs to a list of Typedef objects.
927  - Parses constants to a list of Constant objects.
928  - Parses structs and unions to a list of Structure objects.
929  - Parses defines to a list of Define objects.
930
931  The parser also creates 'typemap' dict which maps every type to its generator
932  object.  This typemap helps manage type dependencies.
933
934  Example usage:
935  parser = StructureParser(open('myfile'))
936  types, constants, structs, defines, typemap = parser.Parse()
937  """
938
939  # Compile regular expressions.
940  _BEGIN_TYPES_TOKEN = '_BEGIN_TYPES'
941  _BEGIN_CONSTANTS_TOKEN = '_BEGIN_CONSTANTS'
942  _BEGIN_STRUCTURES_TOKEN = '_BEGIN_STRUCTURES'
943  _BEGIN_UNIONS_TOKEN = '_BEGIN_UNIONS'
944  _BEGIN_DEFINES_TOKEN = '_BEGIN_DEFINES'
945  _END_TOKEN = '_END'
946  _OLD_TYPE_RE = re.compile(r'^_OLD_TYPE\s+(\w+)$')
947  _NEW_TYPE_RE = re.compile(r'^_NEW_TYPE\s+(\w+)$')
948  _CONSTANTS_SECTION_RE = re.compile(r'^_CONSTANTS.* (\w+)$')
949  _STRUCTURE_SECTION_RE = re.compile(r'^_STRUCTURE\s+(\w+)$')
950  _UNION_SECTION_RE = re.compile(r'^_UNION\s+(\w+)$')
951  _TYPE_RE = re.compile(r'^_TYPE\s+(\w+)$')
952  _NAME_RE = re.compile(r'^_NAME\s+([a-zA-Z0-9_()\[\]/\*\+\-]+)$')
953  _VALUE_RE = re.compile(r'^_VALUE\s+(.+)$')
954  _SIZEOF_RE = re.compile(r'^.*sizeof\(([a-zA-Z0-9_]*)\).*$')
955
956  def __init__(self, in_file):
957    """Initializes a StructureParser instance.
958
959    Args:
960      in_file: A file as returned by open() which has been opened for reading.
961    """
962    self._line = None
963    self._in_file = in_file
964
965  def _NextLine(self):
966    """Gets the next input line.
967
968    Returns:
969      The next input line if another line is available, None otherwise.
970    """
971    try:
972      self._line = self._in_file.next()
973    except StopIteration:
974      self._line = None
975
976  def Parse(self):
977    """Parse everything in a structures file.
978
979    Returns:
980      Lists of objects and a type-map as described in the class documentation.
981      Returns these in the following order: types, constants, structs, defines,
982      typemap.
983    """
984    self._NextLine()
985    types = []
986    constants = []
987    structs = []
988    defines = []
989    typemap = {}
990    while self._line:
991      if self._BEGIN_TYPES_TOKEN == self._line.rstrip():
992        types += self._ParseTypes(typemap)
993      elif self._BEGIN_CONSTANTS_TOKEN == self._line.rstrip():
994        constants += self._ParseConstants(types, typemap)
995      elif self._BEGIN_STRUCTURES_TOKEN == self._line.rstrip():
996        structs += self._ParseStructures(self._STRUCTURE_SECTION_RE, typemap)
997      elif self._BEGIN_UNIONS_TOKEN == self._line.rstrip():
998        structs += self._ParseStructures(self._UNION_SECTION_RE, typemap)
999      elif self._BEGIN_DEFINES_TOKEN == self._line.rstrip():
1000        defines += self._ParseDefines()
1001      else:
1002        print('Invalid file format: %s' % self._line)
1003        break
1004      self._NextLine()
1005    # Empty structs not handled by the extractor.
1006    self._AddEmptyStruct('TPMU_SYM_DETAILS', True, structs, typemap)
1007    # Defines which are used in TPM 2.0 Part 2 but not defined there.
1008    defines.append(Define(
1009        'MAX_CAP_DATA', '(MAX_CAP_BUFFER-sizeof(TPM_CAP)-sizeof(UINT32))'))
1010    defines.append(Define(
1011        'MAX_CAP_ALGS', '(TPM_ALG_LAST - TPM_ALG_FIRST + 1)'))
1012    defines.append(Define(
1013        'MAX_CAP_HANDLES', '(MAX_CAP_DATA/sizeof(TPM_HANDLE))'))
1014    defines.append(Define(
1015        'MAX_CAP_CC', '((TPM_CC_LAST - TPM_CC_FIRST) + 1)'))
1016    defines.append(Define(
1017        'MAX_TPM_PROPERTIES', '(MAX_CAP_DATA/sizeof(TPMS_TAGGED_PROPERTY))'))
1018    defines.append(Define(
1019        'MAX_PCR_PROPERTIES', '(MAX_CAP_DATA/sizeof(TPMS_TAGGED_PCR_SELECT))'))
1020    defines.append(Define(
1021        'MAX_ECC_CURVES', '(MAX_CAP_DATA/sizeof(TPM_ECC_CURVE))'))
1022    defines.append(Define('HASH_COUNT', '3'))
1023    return types, constants, structs, defines, typemap
1024
1025  def _AddEmptyStruct(self, name, is_union, structs, typemap):
1026    """Adds an empty Structure object to |structs| and |typemap|.
1027
1028    Args:
1029      name: The name to assign the new structure.
1030      is_union: A boolean indicating whether the new structure is a union.
1031      structs: A list of structures to which the new object is appended.
1032      typemap: A map of type names to objects to which the new name and object
1033          are added.
1034    """
1035    s = Structure(name, is_union)
1036    structs.append(s)
1037    typemap[name] = s
1038    return
1039
1040  def _ParseTypes(self, typemap):
1041    """Parses a typedefs section.
1042
1043    The current line should be _BEGIN_TYPES and the method will stop parsing
1044    when an _END line is found.
1045
1046    Args:
1047      typemap: A dictionary to which parsed types are added.
1048
1049    Returns:
1050      A list of Typedef objects.
1051    """
1052    types = []
1053    self._NextLine()
1054    while self._END_TOKEN != self._line.rstrip():
1055      match = self._OLD_TYPE_RE.search(self._line)
1056      if not match:
1057        print('Invalid old type: %s' % self._line)
1058        return types
1059      old_type = match.group(1)
1060      self._NextLine()
1061      match = self._NEW_TYPE_RE.search(self._line)
1062      if not match:
1063        print('Invalid new type: %s' % self._line)
1064        return types
1065      new_type = match.group(1)
1066      t = Typedef(old_type, new_type)
1067      types.append(t)
1068      typemap[new_type] = t
1069      self._NextLine()
1070    return types
1071
1072  def _ParseConstants(self, types, typemap):
1073    """Parses a constants section.
1074
1075    The current line should be _BEGIN_CONSTANTS and the method will stop parsing
1076    when an _END line is found. Each group of constants has an associated type
1077    alias. A Typedef object is created for each of these aliases and added to
1078    both |types| and |typemap|.
1079
1080    Args:
1081      types: A list of Typedef objects.
1082      typemap: A dictionary to which parsed types are added.
1083
1084    Returns:
1085      A list of Constant objects.
1086    """
1087    constants = []
1088    self._NextLine()
1089    while self._END_TOKEN != self._line.rstrip():
1090      match = self._CONSTANTS_SECTION_RE.search(self._line)
1091      if not match:
1092        print('Invalid constants section: %s' % self._line)
1093        return constants
1094      constant_typename = match.group(1)
1095      self._NextLine()
1096      match = self._TYPE_RE.search(self._line)
1097      if not match:
1098        print('Invalid constants type: %s' % self._line)
1099        return constants
1100      constant_type = match.group(1)
1101      # Create a typedef for the constant group name (e.g. TPM_RC).
1102      typedef = Typedef(constant_type, constant_typename)
1103      typemap[constant_typename] = typedef
1104      types.append(typedef)
1105      self._NextLine()
1106      match = self._NAME_RE.search(self._line)
1107      if not match:
1108        print('Invalid constant name: %s' % self._line)
1109        return constants
1110      while match:
1111        name = match.group(1)
1112        self._NextLine()
1113        match = self._VALUE_RE.search(self._line)
1114        if not match:
1115          print('Invalid constant value: %s' % self._line)
1116          return constants
1117        value = match.group(1)
1118        constants.append(Constant(constant_typename, name, value))
1119        self._NextLine()
1120        match = self._NAME_RE.search(self._line)
1121    return constants
1122
1123  def _ParseStructures(self, section_re, typemap):
1124    """Parses structures and unions.
1125
1126    The current line should be _BEGIN_STRUCTURES or _BEGIN_UNIONS and the method
1127    will stop parsing when an _END line is found.
1128
1129    Args:
1130      section_re: The regular expression to use for matching section tokens.
1131      typemap: A dictionary to which parsed types are added.
1132
1133    Returns:
1134      A list of Structure objects.
1135    """
1136    structures = []
1137    is_union = section_re == self._UNION_SECTION_RE
1138    self._NextLine()
1139    while self._END_TOKEN != self._line.rstrip():
1140      match = section_re.search(self._line)
1141      if not match:
1142        print('Invalid structure section: %s' % self._line)
1143        return structures
1144      current_structure_name = match.group(1)
1145      current_structure = Structure(current_structure_name, is_union)
1146      self._NextLine()
1147      match = self._TYPE_RE.search(self._line)
1148      if not match:
1149        print('Invalid field type: %s' % self._line)
1150        return structures
1151      while match:
1152        field_type = match.group(1)
1153        self._NextLine()
1154        match = self._NAME_RE.search(self._line)
1155        if not match:
1156          print('Invalid field name: %s' % self._line)
1157          return structures
1158        field_name = match.group(1)
1159        # If the field name includes 'sizeof(SOME_TYPE)', record the dependency
1160        # on SOME_TYPE.
1161        match = self._SIZEOF_RE.search(field_name)
1162        if match:
1163          current_structure.AddDependency(match.group(1))
1164        # Manually change unfortunate names.
1165        if field_name == 'xor':
1166          field_name = 'xor_'
1167        current_structure.AddField(field_type, field_name)
1168        self._NextLine()
1169        match = self._TYPE_RE.search(self._line)
1170      structures.append(current_structure)
1171      typemap[current_structure_name] = current_structure
1172    return structures
1173
1174  def _ParseDefines(self):
1175    """Parses preprocessor defines.
1176
1177    The current line should be _BEGIN_DEFINES and the method will stop parsing
1178    when an _END line is found.
1179
1180    Returns:
1181      A list of Define objects.
1182    """
1183    defines = []
1184    self._NextLine()
1185    while self._END_TOKEN != self._line.rstrip():
1186      match = self._NAME_RE.search(self._line)
1187      if not match:
1188        print('Invalid name: %s' % self._line)
1189        return defines
1190      name = match.group(1)
1191      self._NextLine()
1192      match = self._VALUE_RE.search(self._line)
1193      if not match:
1194        print('Invalid value: %s' % self._line)
1195        return defines
1196      value = match.group(1)
1197      defines.append(Define(name, value))
1198      self._NextLine()
1199    return defines
1200
1201
1202class Command(object):
1203  """Represents a TPM command.
1204
1205  Attributes:
1206    name: The command name (e.g. 'TPM2_Startup').
1207    command_code: The name of the command code constant (e.g. TPM2_CC_Startup).
1208    request_args: A list to hold command input arguments. Each element is a dict
1209        and has these keys:
1210            'type': The argument type.
1211            'name': The argument name.
1212            'command_code': The optional value of the command code constant.
1213            'description': Optional descriptive text for the argument.
1214    response_args: A list identical in form to request_args but to hold command
1215        output arguments.
1216  """
1217
1218  _HANDLE_RE = re.compile(r'TPMI_.H_.*')
1219  _CALLBACK_ARG = """
1220      const %(method_name)sResponse& callback"""
1221  _DELEGATE_ARG = """
1222      AuthorizationDelegate* authorization_delegate"""
1223  _SERIALIZE_ARG = """
1224      std::string* serialized_command"""
1225  _PARSE_ARG = """
1226      const std::string& response"""
1227  _SERIALIZE_FUNCTION_START = """
1228TPM_RC Tpm::SerializeCommand_%(method_name)s(%(method_args)s) {
1229  VLOG(3) << __func__;
1230  TPM_RC rc = TPM_RC_SUCCESS;
1231  TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
1232  UINT32 command_size = 10;  // Header size.
1233  std::string handle_section_bytes;
1234  std::string parameter_section_bytes;"""
1235  _DECLARE_COMMAND_CODE = """
1236  TPM_CC command_code = %(command_code)s;"""
1237  _DECLARE_BOOLEAN = """
1238  bool %(var_name)s = %(value)s;"""
1239  _SERIALIZE_LOCAL_VAR = """
1240  std::string %(var_name)s_bytes;
1241  rc = Serialize_%(var_type)s(
1242      %(var_name)s,
1243      &%(var_name)s_bytes);
1244  if (rc != TPM_RC_SUCCESS) {
1245    return rc;
1246  }"""
1247  _ENCRYPT_PARAMETER = """
1248  if (authorization_delegate) {
1249    // Encrypt just the parameter data, not the size.
1250    std::string tmp = %(var_name)s_bytes.substr(2);
1251    if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
1252      return TRUNKS_RC_ENCRYPTION_FAILED;
1253    }
1254    %(var_name)s_bytes.replace(2, std::string::npos, tmp);
1255  }"""
1256  _HASH_START = """
1257  std::unique_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
1258      crypto::SecureHash::SHA256));"""
1259  _HASH_UPDATE = """
1260  hash->Update(%(var_name)s.data(),
1261               %(var_name)s.size());"""
1262  _APPEND_COMMAND_HANDLE = """
1263  handle_section_bytes += %(var_name)s_bytes;
1264  command_size += %(var_name)s_bytes.size();"""
1265  _APPEND_COMMAND_PARAMETER = """
1266  parameter_section_bytes += %(var_name)s_bytes;
1267  command_size += %(var_name)s_bytes.size();"""
1268  _AUTHORIZE_COMMAND = """
1269  std::string command_hash(32, 0);
1270  hash->Finish(string_as_array(&command_hash), command_hash.size());
1271  std::string authorization_section_bytes;
1272  std::string authorization_size_bytes;
1273  if (authorization_delegate) {
1274    if (!authorization_delegate->GetCommandAuthorization(
1275        command_hash,
1276        is_command_parameter_encryption_possible,
1277        is_response_parameter_encryption_possible,
1278        &authorization_section_bytes)) {
1279      return TRUNKS_RC_AUTHORIZATION_FAILED;
1280    }
1281    if (!authorization_section_bytes.empty()) {
1282      tag = TPM_ST_SESSIONS;
1283      std::string tmp;
1284      rc = Serialize_UINT32(authorization_section_bytes.size(),
1285                            &authorization_size_bytes);
1286      if (rc != TPM_RC_SUCCESS) {
1287        return rc;
1288      }
1289      command_size += authorization_size_bytes.size() +
1290                      authorization_section_bytes.size();
1291    }
1292  }"""
1293  _SERIALIZE_FUNCTION_END = """
1294  *serialized_command = tag_bytes +
1295                        command_size_bytes +
1296                        command_code_bytes +
1297                        handle_section_bytes +
1298                        authorization_size_bytes +
1299                        authorization_section_bytes +
1300                        parameter_section_bytes;
1301  CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
1302  VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
1303                                            serialized_command->size());
1304  return TPM_RC_SUCCESS;
1305}
1306"""
1307  _RESPONSE_PARSER_START = """
1308TPM_RC Tpm::ParseResponse_%(method_name)s(%(method_args)s) {
1309  VLOG(3) << __func__;
1310  VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
1311  TPM_RC rc = TPM_RC_SUCCESS;
1312  std::string buffer(response);"""
1313  _PARSE_LOCAL_VAR = """
1314  %(var_type)s %(var_name)s;
1315  std::string %(var_name)s_bytes;
1316  rc = Parse_%(var_type)s(
1317      &buffer,
1318      &%(var_name)s,
1319      &%(var_name)s_bytes);
1320  if (rc != TPM_RC_SUCCESS) {
1321    return rc;
1322  }"""
1323  _PARSE_ARG_VAR = """
1324  std::string %(var_name)s_bytes;
1325  rc = Parse_%(var_type)s(
1326      &buffer,
1327      %(var_name)s,
1328      &%(var_name)s_bytes);
1329  if (rc != TPM_RC_SUCCESS) {
1330    return rc;
1331  }"""
1332  _RESPONSE_ERROR_CHECK = """
1333  if (response_size != response.size()) {
1334    return TPM_RC_SIZE;
1335  }
1336  if (response_code != TPM_RC_SUCCESS) {
1337    return response_code;
1338  }"""
1339  _RESPONSE_SECTION_SPLIT = """
1340  std::string authorization_section_bytes;
1341  if (tag == TPM_ST_SESSIONS) {
1342    UINT32 parameter_section_size = buffer.size();
1343    rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
1344    if (rc != TPM_RC_SUCCESS) {
1345      return rc;
1346    }
1347    if (parameter_section_size > buffer.size()) {
1348      return TPM_RC_INSUFFICIENT;
1349    }
1350    authorization_section_bytes = buffer.substr(parameter_section_size);
1351    // Keep the parameter section in |buffer|.
1352    buffer.erase(parameter_section_size);
1353  }"""
1354  _AUTHORIZE_RESPONSE = """
1355  std::string response_hash(32, 0);
1356  hash->Finish(string_as_array(&response_hash), response_hash.size());
1357  if (tag == TPM_ST_SESSIONS) {
1358    CHECK(authorization_delegate) << "Authorization delegate missing!";
1359    if (!authorization_delegate->CheckResponseAuthorization(
1360        response_hash,
1361        authorization_section_bytes)) {
1362      return TRUNKS_RC_AUTHORIZATION_FAILED;
1363    }
1364  }"""
1365  _DECRYPT_PARAMETER = """
1366  if (tag == TPM_ST_SESSIONS) {
1367    CHECK(authorization_delegate) << "Authorization delegate missing!";
1368    // Decrypt just the parameter data, not the size.
1369    std::string tmp = %(var_name)s_bytes.substr(2);
1370    if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
1371      return TRUNKS_RC_ENCRYPTION_FAILED;
1372    }
1373    %(var_name)s_bytes.replace(2, std::string::npos, tmp);
1374    rc = Parse_%(var_type)s(
1375        &%(var_name)s_bytes,
1376        %(var_name)s,
1377        nullptr);
1378    if (rc != TPM_RC_SUCCESS) {
1379      return rc;
1380    }
1381  }"""
1382  _RESPONSE_PARSER_END = """
1383  return TPM_RC_SUCCESS;
1384}
1385"""
1386  _ERROR_CALLBACK_START = """
1387void %(method_name)sErrorCallback(
1388    const Tpm::%(method_name)sResponse& callback,
1389    TPM_RC response_code) {
1390  VLOG(1) << __func__;
1391  callback.Run(response_code"""
1392  _ERROR_CALLBACK_ARG = """,
1393               %(arg_type)s()"""
1394  _ERROR_CALLBACK_END = """);
1395}
1396"""
1397  _RESPONSE_CALLBACK_START = """
1398void %(method_name)sResponseParser(
1399    const Tpm::%(method_name)sResponse& callback,
1400    AuthorizationDelegate* authorization_delegate,
1401    const std::string& response) {
1402  VLOG(1) << __func__;
1403  base::Callback<void(TPM_RC)> error_reporter =
1404      base::Bind(%(method_name)sErrorCallback, callback);"""
1405  _DECLARE_ARG_VAR = """
1406  %(var_type)s %(var_name)s;"""
1407  _RESPONSE_CALLBACK_END = """
1408  TPM_RC rc = Tpm::ParseResponse_%(method_name)s(
1409      response,%(method_arg_names_out)s
1410      authorization_delegate);
1411  if (rc != TPM_RC_SUCCESS) {
1412    error_reporter.Run(rc);
1413    return;
1414  }
1415  callback.Run(
1416      rc%(method_arg_names_in)s);
1417}
1418"""
1419  _ASYNC_METHOD = """
1420void Tpm::%(method_name)s(%(method_args)s) {
1421  VLOG(1) << __func__;
1422  base::Callback<void(TPM_RC)> error_reporter =
1423      base::Bind(%(method_name)sErrorCallback, callback);
1424  base::Callback<void(const std::string&)> parser =
1425      base::Bind(%(method_name)sResponseParser,
1426                 callback,
1427                 authorization_delegate);
1428  std::string command;
1429  TPM_RC rc = SerializeCommand_%(method_name)s(%(method_arg_names)s
1430      &command,
1431      authorization_delegate);
1432  if (rc != TPM_RC_SUCCESS) {
1433    error_reporter.Run(rc);
1434    return;
1435  }
1436  transceiver_->SendCommand(command, parser);
1437}
1438"""
1439  _SYNC_METHOD = """
1440TPM_RC Tpm::%(method_name)sSync(%(method_args)s) {
1441  VLOG(1) << __func__;
1442  std::string command;
1443  TPM_RC rc = SerializeCommand_%(method_name)s(%(method_arg_names_in)s
1444      &command,
1445      authorization_delegate);
1446  if (rc != TPM_RC_SUCCESS) {
1447    return rc;
1448  }
1449  std::string response = transceiver_->SendCommandAndWait(command);
1450  rc = ParseResponse_%(method_name)s(
1451      response,%(method_arg_names_out)s
1452      authorization_delegate);
1453  return rc;
1454}
1455"""
1456
1457  def __init__(self, name):
1458    """Initializes a Command instance.
1459
1460    Initially the request_args and response_args attributes are not set.
1461
1462    Args:
1463      name: The command name (e.g. 'TPM2_Startup').
1464    """
1465    self.name = name
1466    self.command_code = ''
1467    self.request_args = None
1468    self.response_args = None
1469
1470  def OutputDeclarations(self, out_file):
1471    """Prints method and callback declaration statements for this command.
1472
1473    Args:
1474      out_file: The output file.
1475    """
1476    self._OutputCallbackSignature(out_file)
1477    self._OutputMethodSignatures(out_file)
1478
1479  def OutputSerializeFunction(self, out_file):
1480    """Generates a serialize function for the command inputs.
1481
1482    Args:
1483      out_file: Generated code is written to this file.
1484    """
1485    # Categorize arguments as either handles or parameters.
1486    handles, parameters = self._SplitArgs(self.request_args)
1487    response_parameters = self._SplitArgs(self.response_args)[1]
1488    out_file.write(self._SERIALIZE_FUNCTION_START % {
1489        'method_name': self._MethodName(),
1490        'method_args': self._SerializeArgs()})
1491    out_file.write(self._DECLARE_COMMAND_CODE % {'command_code':
1492                                                 self.command_code})
1493    out_file.write(self._DECLARE_BOOLEAN % {
1494        'var_name': 'is_command_parameter_encryption_possible',
1495        'value': GetCppBool(parameters and IsTPM2B(parameters[0]['type']))})
1496    out_file.write(self._DECLARE_BOOLEAN % {
1497        'var_name': 'is_response_parameter_encryption_possible',
1498        'value': GetCppBool(response_parameters and
1499                            IsTPM2B(response_parameters[0]['type']))})
1500    # Serialize the command code and all the handles and parameters.
1501    out_file.write(self._SERIALIZE_LOCAL_VAR % {'var_name': 'command_code',
1502                                                'var_type': 'TPM_CC'})
1503    for arg in self.request_args:
1504      out_file.write(self._SERIALIZE_LOCAL_VAR % {'var_name': arg['name'],
1505                                                  'var_type': arg['type']})
1506    # Encrypt the first parameter (before doing authorization) if necessary.
1507    if parameters and IsTPM2B(parameters[0]['type']):
1508      out_file.write(self._ENCRYPT_PARAMETER % {'var_name':
1509                                                parameters[0]['name']})
1510    # Compute the command hash and construct handle and parameter sections.
1511    out_file.write(self._HASH_START)
1512    out_file.write(self._HASH_UPDATE % {'var_name': 'command_code_bytes'})
1513    for handle in handles:
1514      out_file.write(self._HASH_UPDATE % {'var_name':
1515                                          '%s_name' % handle['name']})
1516      out_file.write(self._APPEND_COMMAND_HANDLE % {'var_name':
1517                                                    handle['name']})
1518    for parameter in parameters:
1519      out_file.write(self._HASH_UPDATE % {'var_name':
1520                                          '%s_bytes' % parameter['name']})
1521      out_file.write(self._APPEND_COMMAND_PARAMETER % {'var_name':
1522                                                       parameter['name']})
1523    # Do authorization based on the hash.
1524    out_file.write(self._AUTHORIZE_COMMAND)
1525    # Now that the tag and size are finalized, serialize those.
1526    out_file.write(self._SERIALIZE_LOCAL_VAR %
1527                   {'var_name': 'tag',
1528                    'var_type': 'TPMI_ST_COMMAND_TAG'})
1529    out_file.write(self._SERIALIZE_LOCAL_VAR % {'var_name': 'command_size',
1530                                                'var_type': 'UINT32'})
1531    out_file.write(self._SERIALIZE_FUNCTION_END)
1532
1533  def OutputParseFunction(self, out_file):
1534    """Generates a parse function for the command outputs.
1535
1536    Args:
1537      out_file: Generated code is written to this file.
1538    """
1539    out_file.write(self._RESPONSE_PARSER_START % {
1540        'method_name': self._MethodName(),
1541        'method_args': self._ParseArgs()})
1542    # Parse the header -- this should always exist.
1543    out_file.write(self._PARSE_LOCAL_VAR % {'var_name': 'tag',
1544                                            'var_type': 'TPM_ST'})
1545    out_file.write(self._PARSE_LOCAL_VAR % {'var_name': 'response_size',
1546                                            'var_type': 'UINT32'})
1547    out_file.write(self._PARSE_LOCAL_VAR % {'var_name': 'response_code',
1548                                            'var_type': 'TPM_RC'})
1549    # Handle the error case.
1550    out_file.write(self._RESPONSE_ERROR_CHECK)
1551    # Categorize arguments as either handles or parameters.
1552    handles, parameters = self._SplitArgs(self.response_args)
1553    # Parse any handles.
1554    for handle in handles:
1555      out_file.write(self._PARSE_ARG_VAR % {'var_name': handle['name'],
1556                                            'var_type': handle['type']})
1557    # Setup a serialized command code which is needed for the response hash.
1558    out_file.write(self._DECLARE_COMMAND_CODE % {'command_code':
1559                                                 self.command_code})
1560    out_file.write(self._SERIALIZE_LOCAL_VAR % {'var_name': 'command_code',
1561                                                'var_type': 'TPM_CC'})
1562    # Split out the authorization section.
1563    out_file.write(self._RESPONSE_SECTION_SPLIT)
1564    # Compute the response hash.
1565    out_file.write(self._HASH_START)
1566    out_file.write(self._HASH_UPDATE % {'var_name': 'response_code_bytes'})
1567    out_file.write(self._HASH_UPDATE % {'var_name': 'command_code_bytes'})
1568    out_file.write(self._HASH_UPDATE % {'var_name': 'buffer'})
1569    # Do authorization related stuff.
1570    out_file.write(self._AUTHORIZE_RESPONSE)
1571    # Parse response parameters.
1572    for arg in parameters:
1573      out_file.write(self._PARSE_ARG_VAR % {'var_name': arg['name'],
1574                                            'var_type': arg['type']})
1575    if parameters and IsTPM2B(parameters[0]['type']):
1576      out_file.write(self._DECRYPT_PARAMETER % {'var_name':
1577                                                parameters[0]['name'],
1578                                                'var_type':
1579                                                parameters[0]['type']})
1580    out_file.write(self._RESPONSE_PARSER_END)
1581
1582  def OutputMethodImplementation(self, out_file):
1583    """Generates the implementation of a Tpm class method for this command.
1584
1585    The method assembles a command to be sent unmodified to the TPM and invokes
1586    the CommandTransceiver with the command. Errors are reported directly to the
1587    response callback via the error callback (see OutputErrorCallback).
1588
1589    Args:
1590      out_file: Generated code is written to this file.
1591    """
1592    out_file.write(self._ASYNC_METHOD % {
1593        'method_name': self._MethodName(),
1594        'method_args': self._AsyncArgs(),
1595        'method_arg_names': self._ArgNameList(self._RequestArgs(),
1596                                              trailing_comma=True)})
1597    out_file.write(self._SYNC_METHOD % {
1598        'method_name': self._MethodName(),
1599        'method_args': self._SyncArgs(),
1600        'method_arg_names_in': self._ArgNameList(self._RequestArgs(),
1601                                                 trailing_comma=True),
1602        'method_arg_names_out': self._ArgNameList(self.response_args,
1603                                                  trailing_comma=True)})
1604
1605  def OutputErrorCallback(self, out_file):
1606    """Generates the implementation of an error callback for this command.
1607
1608    The error callback simply calls the command response callback with the error
1609    as the first argument and default values for all other arguments.
1610
1611    Args:
1612      out_file: Generated code is written to this file.
1613    """
1614    out_file.write(self._ERROR_CALLBACK_START % {'method_name':
1615                                                 self._MethodName()})
1616    for arg in self.response_args:
1617      out_file.write(self._ERROR_CALLBACK_ARG % {'arg_type': arg['type']})
1618    out_file.write(self._ERROR_CALLBACK_END)
1619
1620  def OutputResponseCallback(self, out_file):
1621    """Generates the implementation of a response callback for this command.
1622
1623    The response callback takes the unmodified response from the TPM, parses it,
1624    and invokes the original response callback with the parsed response args.
1625    Errors during parsing or from the TPM are reported directly to the response
1626    callback via the error callback (see OutputErrorCallback).
1627
1628    Args:
1629      out_file: Generated code is written to this file.
1630    """
1631    out_file.write(self._RESPONSE_CALLBACK_START % {'method_name':
1632                                                    self._MethodName()})
1633    for arg in self.response_args:
1634      out_file.write(self._DECLARE_ARG_VAR % {'var_type': arg['type'],
1635                                              'var_name': arg['name']})
1636    out_file.write(self._RESPONSE_CALLBACK_END % {
1637        'method_name': self._MethodName(),
1638        'method_arg_names_in': self._ArgNameList(self.response_args,
1639                                                 leading_comma=True),
1640        'method_arg_names_out': self._ArgNameList(self.response_args,
1641                                                  prefix='&',
1642                                                  trailing_comma=True)})
1643
1644  def GetNumberOfRequestHandles(self):
1645    """Returns the number of input handles for this command."""
1646    return len(self._SplitArgs(self.request_args)[0])
1647
1648  def GetNumberOfResponseHandles(self):
1649    """Returns the number of output handles for this command."""
1650    return len(self._SplitArgs(self.response_args)[0])
1651
1652  def _OutputMethodSignatures(self, out_file):
1653    """Prints method declaration statements for this command.
1654
1655    This includes a method to serialize a request, a method to parse a response,
1656    and methods for synchronous and asynchronous calls.
1657
1658    Args:
1659      out_file: The output file.
1660    """
1661    out_file.write('  static TPM_RC SerializeCommand_%s(%s);\n' % (
1662        self._MethodName(), self._SerializeArgs()))
1663    out_file.write('  static TPM_RC ParseResponse_%s(%s);\n' % (
1664        self._MethodName(), self._ParseArgs()))
1665    out_file.write('  virtual void %s(%s);\n' % (self._MethodName(),
1666                                                 self._AsyncArgs()))
1667    out_file.write('  virtual TPM_RC %sSync(%s);\n' % (self._MethodName(),
1668                                                       self._SyncArgs()))
1669
1670  def _OutputCallbackSignature(self, out_file):
1671    """Prints a callback typedef for this command.
1672
1673    Args:
1674      out_file: The output file.
1675    """
1676    args = self._InputArgList(self.response_args)
1677    if args:
1678      args = ',' + args
1679    args = '\n      TPM_RC response_code' + args
1680    out_file.write('  typedef base::Callback<void(%s)> %sResponse;\n' %
1681                   (args, self._MethodName()))
1682
1683  def _MethodName(self):
1684    """Creates an appropriate generated method name for the command.
1685
1686    We use the command name without the TPM2_ prefix.
1687
1688    Returns:
1689      The method name.
1690    """
1691    if not self.name.startswith('TPM2_'):
1692      return self.name
1693    return self.name[5:]
1694
1695  def _InputArgList(self, args):
1696    """Formats a list of input arguments for use in a function declaration.
1697
1698    Args:
1699      args: An argument list in the same form as the request_args and
1700          response_args attributes.
1701
1702    Returns:
1703      A string which can be used in a function declaration.
1704    """
1705    if args:
1706      arg_list = ['const %(type)s& %(name)s' % a for a in args]
1707      return '\n      ' + ',\n      '.join(arg_list)
1708    return ''
1709
1710  def _OutputArgList(self, args):
1711    """Formats a list of output arguments for use in a function declaration.
1712
1713    Args:
1714      args: An argument list in the same form as the request_args and
1715          response_args attributes.
1716
1717    Returns:
1718      A string which can be used in a function declaration.
1719    """
1720    if args:
1721      arg_list = ['%(type)s* %(name)s' % a for a in args]
1722      return '\n      ' + ',\n      '.join(arg_list)
1723    return ''
1724
1725  def _ArgNameList(self, args, prefix='', leading_comma=False,
1726                   trailing_comma=False):
1727    """Formats a list of arguments for use in a function call statement.
1728
1729    Args:
1730      args: An argument list in the same form as the request_args and
1731          response_args attributes.
1732      prefix: A prefix to be prepended to each argument.
1733      leading_comma: Whether to include a comma before the first argument.
1734      trailing_comma: Whether to include a comma after the last argument.
1735
1736    Returns:
1737      A string which can be used in a function call statement.
1738    """
1739    if args:
1740      arg_list = [(prefix + a['name']) for a in args]
1741      header = ''
1742      if leading_comma:
1743        header = ','
1744      trailer = ''
1745      if trailing_comma:
1746        trailer = ','
1747      return header + '\n      ' + ',\n      '.join(arg_list) + trailer
1748    return ''
1749
1750  def _SplitArgs(self, args):
1751    """Splits a list of args into handles and parameters."""
1752    handles = []
1753    parameters = []
1754    # These commands have handles that are serialized into the parameter
1755    # section.
1756    command_handle_parameters = {
1757        'TPM_CC_FlushContext': 'TPMI_DH_CONTEXT',
1758        'TPM_CC_Hash': 'TPMI_RH_HIERARCHY',
1759        'TPM_CC_LoadExternal': 'TPMI_RH_HIERARCHY',
1760        'TPM_CC_SequenceComplete': 'TPMI_RH_HIERARCHY',
1761    }
1762    # Handle type that appears in the handle section.
1763    always_handle = set(['TPM_HANDLE'])
1764    # Handle types that always appear as command parameters.
1765    always_parameter = set(['TPMI_RH_ENABLES', 'TPMI_DH_PERSISTENT'])
1766    if self.command_code in command_handle_parameters:
1767      always_parameter.add(command_handle_parameters[self.command_code])
1768    for arg in args:
1769      if (arg['type'] in always_handle or
1770          (self._HANDLE_RE.search(arg['type']) and
1771           arg['type'] not in always_parameter)):
1772        handles.append(arg)
1773      else:
1774        parameters.append(arg)
1775    return handles, parameters
1776
1777  def _RequestArgs(self):
1778    """Computes the argument list for a Tpm request.
1779
1780    For every handle argument a handle name argument is added.
1781    """
1782    handles, parameters = self._SplitArgs(self.request_args)
1783    args = []
1784    # Add a name argument for every handle.  We'll need it to compute cpHash.
1785    for handle in handles:
1786      args.append(handle)
1787      args.append({'type': 'std::string',
1788                   'name': '%s_name' % handle['name']})
1789    for parameter in parameters:
1790      args.append(parameter)
1791    return args
1792
1793  def _AsyncArgs(self):
1794    """Returns a formatted argument list for an asynchronous method."""
1795    args = self._InputArgList(self._RequestArgs())
1796    if args:
1797      args += ','
1798    return (args + self._DELEGATE_ARG + ',' +
1799            self._CALLBACK_ARG % {'method_name': self._MethodName()})
1800
1801  def _SyncArgs(self):
1802    """Returns a formatted argument list for a synchronous method."""
1803    request_arg_list = self._InputArgList(self._RequestArgs())
1804    if request_arg_list:
1805      request_arg_list += ','
1806    response_arg_list = self._OutputArgList(self.response_args)
1807    if response_arg_list:
1808      response_arg_list += ','
1809    return request_arg_list + response_arg_list + self._DELEGATE_ARG
1810
1811  def _SerializeArgs(self):
1812    """Returns a formatted argument list for a request-serialize method."""
1813    args = self._InputArgList(self._RequestArgs())
1814    if args:
1815      args += ','
1816    return args + self._SERIALIZE_ARG + ',' + self._DELEGATE_ARG
1817
1818  def _ParseArgs(self):
1819    """Returns a formatted argument list for a response-parse method."""
1820    args = self._OutputArgList(self.response_args)
1821    if args:
1822      args = ',' + args
1823    return self._PARSE_ARG + args + ',' + self._DELEGATE_ARG
1824
1825
1826class CommandParser(object):
1827  """Command definition parser.
1828
1829  The input text file is extracted from the PDF file containing the TPM
1830  command specification from the Trusted Computing Group. The syntax
1831  of the text file is defined by extract_commands.sh.
1832  """
1833
1834  # Regular expressions to pull relevant bits from annotated lines.
1835  _INPUT_START_RE = re.compile(r'^_INPUT_START\s+(\w+)$')
1836  _OUTPUT_START_RE = re.compile(r'^_OUTPUT_START\s+(\w+)$')
1837  _TYPE_RE = re.compile(r'^_TYPE\s+(\w+)$')
1838  _NAME_RE = re.compile(r'^_NAME\s+(\w+)$')
1839  # Pull the command code from a comment like: _COMMENT TPM_CC_Startup {NV}.
1840  _COMMENT_CC_RE = re.compile(r'^_COMMENT\s+(TPM_CC_\w+).*$')
1841  _COMMENT_RE = re.compile(r'^_COMMENT\s+(.*)')
1842  # Args which are handled internally by the generated method.
1843  _INTERNAL_ARGS = ('tag', 'Tag', 'commandSize', 'commandCode', 'responseSize',
1844                    'responseCode', 'returnCode')
1845
1846  def __init__(self, in_file):
1847    """Initializes a CommandParser instance.
1848
1849    Args:
1850      in_file: A file as returned by open() which has been opened for reading.
1851    """
1852    self._line = None
1853    self._in_file = in_file
1854
1855  def _NextLine(self):
1856    """Gets the next input line.
1857
1858    Returns:
1859      The next input line if another line is available, None otherwise.
1860    """
1861    try:
1862      self._line = self._in_file.next()
1863    except StopIteration:
1864      self._line = None
1865
1866  def Parse(self):
1867    """Parses everything in a commands file.
1868
1869    Returns:
1870      A list of extracted Command objects.
1871    """
1872    commands = []
1873    self._NextLine()
1874    if self._line != '_BEGIN\n':
1875      print('Invalid format for first line: %s\n' % self._line)
1876      return commands
1877    self._NextLine()
1878
1879    while self._line != '_END\n':
1880      cmd = self._ParseCommand()
1881      if not cmd:
1882        break
1883      commands.append(cmd)
1884    return commands
1885
1886  def _ParseCommand(self):
1887    """Parses inputs and outputs for a single TPM command.
1888
1889    Returns:
1890      A single Command object.
1891    """
1892    match = self._INPUT_START_RE.search(self._line)
1893    if not match:
1894      print('Cannot match command input from line: %s\n' % self._line)
1895      return None
1896    name = match.group(1)
1897    cmd = Command(name)
1898    self._NextLine()
1899    cmd.request_args = self._ParseCommandArgs(cmd)
1900    match = self._OUTPUT_START_RE.search(self._line)
1901    if not match or match.group(1) != name:
1902      print('Cannot match command output from line: %s\n' % self._line)
1903      return None
1904    self._NextLine()
1905    cmd.response_args = self._ParseCommandArgs(cmd)
1906    request_var_names = set([arg['name'] for arg in cmd.request_args])
1907    for arg in cmd.response_args:
1908      if arg['name'] in request_var_names:
1909        arg['name'] += '_out'
1910    if not cmd.command_code:
1911      print('Command code not found for %s' % name)
1912      return None
1913    return cmd
1914
1915  def _ParseCommandArgs(self, cmd):
1916    """Parses a set of arguments for a command.
1917
1918    The arguments may be input or output arguments.
1919
1920    Args:
1921      cmd: The current Command object. The command_code attribute will be set if
1922          such a constant is parsed.
1923
1924    Returns:
1925      A list of arguments in the same form as the Command.request_args and
1926      Command.response_args attributes.
1927    """
1928    args = []
1929    match = self._TYPE_RE.search(self._line)
1930    while match:
1931      arg_type = match.group(1)
1932      self._NextLine()
1933      match = self._NAME_RE.search(self._line)
1934      if not match:
1935        print('Cannot match argument name from line: %s\n' % self._line)
1936        break
1937      arg_name = match.group(1)
1938      self._NextLine()
1939      match = self._COMMENT_CC_RE.search(self._line)
1940      if match:
1941        cmd.command_code = match.group(1)
1942      match = self._COMMENT_RE.search(self._line)
1943      if match:
1944        self._NextLine()
1945      if arg_name not in self._INTERNAL_ARGS:
1946        args.append({'type': arg_type,
1947                     'name': FixName(arg_name)})
1948      match = self._TYPE_RE.search(self._line)
1949    return args
1950
1951
1952def GenerateHandleCountFunctions(commands, out_file):
1953  """Generates the GetNumberOf*Handles functions given a list of commands.
1954
1955  Args:
1956    commands: A list of Command objects.
1957    out_file: The output file.
1958  """
1959  out_file.write(_HANDLE_COUNT_FUNCTION_START % {'handle_type': 'Request'})
1960  for command in commands:
1961    out_file.write(_HANDLE_COUNT_FUNCTION_CASE %
1962                   {'command_code': command.command_code,
1963                    'handle_count': command.GetNumberOfRequestHandles()})
1964  out_file.write(_HANDLE_COUNT_FUNCTION_END)
1965  out_file.write(_HANDLE_COUNT_FUNCTION_START % {'handle_type': 'Response'})
1966  for command in commands:
1967    out_file.write(_HANDLE_COUNT_FUNCTION_CASE %
1968                   {'command_code': command.command_code,
1969                    'handle_count': command.GetNumberOfResponseHandles()})
1970  out_file.write(_HANDLE_COUNT_FUNCTION_END)
1971
1972
1973def GenerateHeader(types, constants, structs, defines, typemap, commands):
1974  """Generates a header file with declarations for all given generator objects.
1975
1976  Args:
1977    types: A list of Typedef objects.
1978    constants: A list of Constant objects.
1979    structs: A list of Structure objects.
1980    defines: A list of Define objects.
1981    typemap: A dict mapping type names to the corresponding object.
1982    commands: A list of Command objects.
1983  """
1984  out_file = open(_OUTPUT_FILE_H, 'w')
1985  out_file.write(_COPYRIGHT_HEADER)
1986  guard_name = 'TRUNKS_%s_' % _OUTPUT_FILE_H.upper().replace('.', '_')
1987  out_file.write(_HEADER_FILE_GUARD_HEADER % {'name': guard_name})
1988  out_file.write(_HEADER_FILE_INCLUDES)
1989  out_file.write(_NAMESPACE_BEGIN)
1990  out_file.write(_FORWARD_DECLARATIONS)
1991  out_file.write('\n')
1992  # These types are built-in or defined by <stdint.h>; they serve as base cases
1993  # when defining type dependencies.
1994  defined_types = set(_BASIC_TYPES)
1995  # Generate defines.  These must be generated before any other code.
1996  for define in defines:
1997    define.Output(out_file)
1998  out_file.write('\n')
1999  # Generate typedefs.  These are declared before structs because they are not
2000  # likely to depend on structs and when they do a simple forward declaration
2001  # for the struct can be generated.  This improves the readability of the
2002  # generated code.
2003  for typedef in types:
2004    typedef.Output(out_file, defined_types, typemap)
2005  out_file.write('\n')
2006  # Generate constant definitions.  Again, generated before structs to improve
2007  # readability.
2008  for constant in constants:
2009    constant.Output(out_file, defined_types, typemap)
2010  out_file.write('\n')
2011  # Generate structs.  All non-struct dependencies should be already declared.
2012  for struct in structs:
2013    struct.Output(out_file, defined_types, typemap)
2014  # Helper function declarations.
2015  out_file.write(_FUNCTION_DECLARATIONS)
2016  # Generate serialize / parse function declarations.
2017  for basic_type in _BASIC_TYPES:
2018    out_file.write(_SERIALIZE_DECLARATION % {'type': basic_type})
2019  for typedef in types:
2020    out_file.write(_SERIALIZE_DECLARATION % {'type': typedef.new_type})
2021  for struct in structs:
2022    out_file.write(_SERIALIZE_DECLARATION % {'type': struct.name})
2023    if struct.IsSimpleTPM2B():
2024      out_file.write(_SIMPLE_TPM2B_HELPERS_DECLARATION % {'type': struct.name})
2025    elif struct.IsComplexTPM2B():
2026      out_file.write(_COMPLEX_TPM2B_HELPERS_DECLARATION % {
2027          'type': struct.name,
2028          'inner_type': struct.fields[1][0]})
2029  # Generate a declaration for a 'Tpm' class, which includes one method for
2030  # every TPM 2.0 command.
2031  out_file.write(_CLASS_BEGIN)
2032  for command in commands:
2033    command.OutputDeclarations(out_file)
2034  out_file.write(_CLASS_END)
2035  out_file.write(_NAMESPACE_END)
2036  out_file.write(_HEADER_FILE_GUARD_FOOTER % {'name': guard_name})
2037  out_file.close()
2038
2039
2040def GenerateImplementation(types, structs, typemap, commands):
2041  """Generates implementation code for each command.
2042
2043  Args:
2044    types: A list of Typedef objects.
2045    structs: A list of Structure objects.
2046    typemap: A dict mapping type names to the corresponding object.
2047    commands: A list of Command objects.
2048  """
2049  out_file = open(_OUTPUT_FILE_CC, 'w')
2050  out_file.write(_COPYRIGHT_HEADER)
2051  out_file.write(_LOCAL_INCLUDE % {'filename': _OUTPUT_FILE_H})
2052  out_file.write(_IMPLEMENTATION_FILE_INCLUDES)
2053  out_file.write(_NAMESPACE_BEGIN)
2054  GenerateHandleCountFunctions(commands, out_file)
2055  serialized_types = set(_BASIC_TYPES)
2056  for basic_type in _BASIC_TYPES:
2057    out_file.write(_SERIALIZE_BASIC_TYPE % {'type': basic_type})
2058  for typedef in types:
2059    typedef.OutputSerialize(out_file, serialized_types, typemap)
2060  for struct in structs:
2061    struct.OutputSerialize(out_file, serialized_types, typemap)
2062  for command in commands:
2063    command.OutputSerializeFunction(out_file)
2064    command.OutputParseFunction(out_file)
2065    command.OutputErrorCallback(out_file)
2066    command.OutputResponseCallback(out_file)
2067    command.OutputMethodImplementation(out_file)
2068  out_file.write(_NAMESPACE_END)
2069  out_file.close()
2070
2071
2072def FormatFile(filename):
2073    subprocess.call(['clang-format', '-i', '-style=file', filename])
2074
2075
2076def main():
2077  """A main function.
2078
2079  Both a TPM structures file and commands file are parsed and C++ header and C++
2080  implementation file are generated.
2081
2082  Positional Args:
2083    structures_file: The extracted TPM structures file.
2084    commands_file: The extracted TPM commands file.
2085  """
2086  parser = argparse.ArgumentParser(description='TPM 2.0 code generator')
2087  parser.add_argument('structures_file')
2088  parser.add_argument('commands_file')
2089  args = parser.parse_args()
2090  structure_parser = StructureParser(open(args.structures_file))
2091  types, constants, structs, defines, typemap = structure_parser.Parse()
2092  command_parser = CommandParser(open(args.commands_file))
2093  commands = command_parser.Parse()
2094  GenerateHeader(types, constants, structs, defines, typemap, commands)
2095  GenerateImplementation(types, structs, typemap, commands)
2096  FormatFile(_OUTPUT_FILE_H)
2097  FormatFile(_OUTPUT_FILE_CC)
2098  print('Processed %d commands.' % len(commands))
2099
2100
2101if __name__ == '__main__':
2102  main()
2103