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