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