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