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 import subprocess
     77 
     78 import 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 = """
    139 namespace trunks {
    140 """
    141 _NAMESPACE_END = """
    142 }  // namespace trunks
    143 """
    144 _FORWARD_DECLARATIONS = """
    145 class AuthorizationDelegate;
    146 class CommandTransceiver;
    147 """
    148 _FUNCTION_DECLARATIONS = """
    149 TRUNKS_EXPORT size_t GetNumberOfRequestHandles(TPM_CC command_code);
    150 TRUNKS_EXPORT size_t GetNumberOfResponseHandles(TPM_CC command_code);
    151 """
    152 _CLASS_BEGIN = """
    153 class 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 = """
    168 TPM_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 
    189 TPM_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 = """
    219 TRUNKS_EXPORT TPM_RC Serialize_%(type)s(
    220     const %(type)s& value,
    221     std::string* buffer);
    222 
    223 TRUNKS_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 = """
    230 TRUNKS_EXPORT %(type)s Make_%(type)s(
    231     const std::string& bytes);
    232 TRUNKS_EXPORT std::string StringFrom_%(type)s(
    233     const %(type)s& tpm2b);
    234 """
    235 _COMPLEX_TPM2B_HELPERS_DECLARATION = """
    236 TRUNKS_EXPORT %(type)s Make_%(type)s(
    237     const %(inner_type)s& inner);
    238 """
    239 
    240 _HANDLE_COUNT_FUNCTION_START = """
    241 size_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 
    252 def 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 
    263 def IsTPM2B(name):
    264   return name.startswith('TPM2B_')
    265 
    266 
    267 def GetCppBool(condition):
    268   if condition:
    269     return 'true'
    270   return 'false'
    271 
    272 
    273 class 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 = """
    283 TPM_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 = """
    291 TPM_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 
    365 class 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 
    407 class 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 = """
    425 TPM_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 = """
    471 TPM_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 = """
    516 TPM_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 = """
    545 TPM_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 
    596 std::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 
    889 class 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 
    919 class 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 
   1202 class 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 = """
   1228 TPM_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(base::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 = """
   1308 TPM_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(base::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 = """
   1387 void %(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 = """
   1398 void %(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 = """
   1420 void 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 = """
   1440 TPM_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 
   1826 class 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 
   1952 def 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 
   1973 def 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 
   2040 def 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 
   2072 def FormatFile(filename):
   2073     subprocess.call(['clang-format', '-i', '-style=file', filename])
   2074 
   2075 
   2076 def 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 
   2101 if __name__ == '__main__':
   2102   main()
   2103