1ef87f3e63b93ff722a8cbcee9c54d55d085221a3Darren Krahn#!/usr/bin/python2
264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
3bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi#
4bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi# Copyright (C) 2014 The Android Open Source Project
5bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi#
6bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi# Licensed under the Apache License, Version 2.0 (the "License");
7bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi# you may not use this file except in compliance with the License.
8bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi# You may obtain a copy of the License at
9bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi#
10bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi#      http://www.apache.org/licenses/LICENSE-2.0
11bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi#
12bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi# Unless required by applicable law or agreed to in writing, software
13bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi# distributed under the License is distributed on an "AS IS" BASIS,
14bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi# See the License for the specific language governing permissions and
16bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi# limitations under the License.
17bbef5dff2b94fef72012e721cd6124cd87621af4Utkarsh Sanghi#
1864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
1964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn"""A code generator for TPM 2.0 structures and commands.
2064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
2164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren KrahnThe generator takes as input a structures file as emitted by the
2264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahnextract_structures.sh script and a commands file as emitted by the
2364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahnextract_commands.sh script.  It outputs valid C++ into tpm_generated.{h,cc}.
2464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
2564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren KrahnThe input grammar is documented in the extract_* scripts. Sample input for
2664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahnstructures looks like this:
2764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_BEGIN_TYPES
2864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_OLD_TYPE UINT32
2964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_NEW_TYPE TPM_HANDLE
3064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_END
3164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_BEGIN_CONSTANTS
3264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_CONSTANTS (UINT32) TPM_SPEC
3364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_TYPE UINT32
3464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_NAME TPM_SPEC_FAMILY
3564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_VALUE 0x322E3000
3664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_NAME TPM_SPEC_LEVEL
3764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_VALUE 00
3864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_END
3964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_BEGIN_STRUCTURES
4064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_STRUCTURE TPMS_TIME_INFO
4164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_TYPE UINT64
4264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_NAME time
4364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_TYPE TPMS_CLOCK_INFO
4464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_NAME clockInfo
4564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_END
4664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
4764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren KrahnSample input for commands looks like this:
4864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_BEGIN
4964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_INPUT_START TPM2_Startup
5064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_TYPE TPMI_ST_COMMAND_TAG
5164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_NAME tag
5264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_COMMENT TPM_ST_NO_SESSIONS
5364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_TYPE UINT32
5464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_NAME commandSize
5564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_TYPE TPM_CC
5664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_NAME commandCode
5764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_COMMENT TPM_CC_Startup {NV}
5864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_TYPE TPM_SU
5964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_NAME startupType
6064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_COMMENT TPM_SU_CLEAR or TPM_SU_STATE
6164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_OUTPUT_START TPM2_Startup
6264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_TYPE TPM_ST
6364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_NAME tag
6464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_COMMENT see clause 8
6564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_TYPE UINT32
6664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_NAME responseSize
6764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_TYPE TPM_RC
6864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_NAME responseCode
6964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn_END
7064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn"""
7164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
7289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahnfrom __future__ import print_function
7389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
7464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahnimport argparse
7564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahnimport re
7664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
77b49375c15718568c70ebfd55eaee790a2b693944Darren Krahnimport union_selectors
7864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
79e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn_BASIC_TYPES = ['uint8_t', 'int8_t', 'int', 'uint16_t', 'int16_t',
80e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn                'uint32_t', 'int32_t', 'uint64_t', 'int64_t']
81b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn_OUTPUT_FILE_H = 'tpm_generated.h'
82b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn_OUTPUT_FILE_CC = 'tpm_generated.cc'
8389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn_COPYRIGHT_HEADER = (
84df1a065bda6422a3f2c013c3a63bb0e0f39150a8Darren Krahn    '//\n'
85df1a065bda6422a3f2c013c3a63bb0e0f39150a8Darren Krahn    '// Copyright (C) 2015 The Android Open Source Project\n'
86df1a065bda6422a3f2c013c3a63bb0e0f39150a8Darren Krahn    '//\n'
87df1a065bda6422a3f2c013c3a63bb0e0f39150a8Darren Krahn    '// Licensed under the Apache License, Version 2.0 (the "License");\n'
88df1a065bda6422a3f2c013c3a63bb0e0f39150a8Darren Krahn    '// you may not use this file except in compliance with the License.\n'
89df1a065bda6422a3f2c013c3a63bb0e0f39150a8Darren Krahn    '// You may obtain a copy of the License at\n'
90df1a065bda6422a3f2c013c3a63bb0e0f39150a8Darren Krahn    '//\n'
91df1a065bda6422a3f2c013c3a63bb0e0f39150a8Darren Krahn    '//      http://www.apache.org/licenses/LICENSE-2.0\n'
92df1a065bda6422a3f2c013c3a63bb0e0f39150a8Darren Krahn    '//\n'
93df1a065bda6422a3f2c013c3a63bb0e0f39150a8Darren Krahn    '// Unless required by applicable law or agreed to in writing, software\n'
94df1a065bda6422a3f2c013c3a63bb0e0f39150a8Darren Krahn    '// distributed under the License is distributed on an "AS IS" BASIS,\n'
955f8ca6f3d1405102961386e2747400d183527507Utkarsh Sanghi    '// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or '
96df1a065bda6422a3f2c013c3a63bb0e0f39150a8Darren Krahn    'implied.\n'
97df1a065bda6422a3f2c013c3a63bb0e0f39150a8Darren Krahn    '// See the License for the specific language governing permissions and\n'
98df1a065bda6422a3f2c013c3a63bb0e0f39150a8Darren Krahn    '// limitations under the License.\n'
99df1a065bda6422a3f2c013c3a63bb0e0f39150a8Darren Krahn    '//\n\n'
10089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    '// THIS CODE IS GENERATED - DO NOT MODIFY!\n')
101b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn_HEADER_FILE_GUARD_HEADER = """
102b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn#ifndef %(name)s
103b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn#define %(name)s
104b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
105b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn_HEADER_FILE_GUARD_FOOTER = """
106b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn#endif  // %(name)s
107b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
108b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn_HEADER_FILE_INCLUDES = """
109b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn#include <string>
110b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn
111b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn#include <base/callback_forward.h>
112df1a065bda6422a3f2c013c3a63bb0e0f39150a8Darren Krahn#include <base/macros.h>
113ef87f3e63b93ff722a8cbcee9c54d55d085221a3Darren Krahn
114ef87f3e63b93ff722a8cbcee9c54d55d085221a3Darren Krahn#include "trunks/trunks_export.h"
115b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
116b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn_IMPLEMENTATION_FILE_INCLUDES = """
117e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn#include <string>
118e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn
119b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn#include <base/bind.h>
120b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn#include <base/callback.h>
121b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn#include <base/logging.h>
122df1a065bda6422a3f2c013c3a63bb0e0f39150a8Darren Krahn#include <base/macros.h>
123a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn#include <base/stl_util.h>
12403d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn#include <base/strings/string_number_conversions.h>
125b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn#include <base/sys_byteorder.h>
126a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn#include <crypto/secure_hash.h>
127b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn
128e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn#include "trunks/authorization_delegate.h"
1292c1ce244d871c38f48e6bef8af854fa4e7f30c08Darren Krahn#include "trunks/command_transceiver.h"
130a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn#include "trunks/error_codes.h"
1312c1ce244d871c38f48e6bef8af854fa4e7f30c08Darren Krahn
132b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
133b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn_LOCAL_INCLUDE = """
134a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn#include "trunks/%(filename)s"
135b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
136b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn_NAMESPACE_BEGIN = """
137b0f7d258e26830ebace9876cad07e6aefe8e2780Darren Krahnnamespace trunks {
138b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
139b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn_NAMESPACE_END = """
140b0f7d258e26830ebace9876cad07e6aefe8e2780Darren Krahn}  // namespace trunks
141b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
1422c1ce244d871c38f48e6bef8af854fa4e7f30c08Darren Krahn_FORWARD_DECLARATIONS = """
1432c1ce244d871c38f48e6bef8af854fa4e7f30c08Darren Krahnclass AuthorizationDelegate;
1442c1ce244d871c38f48e6bef8af854fa4e7f30c08Darren Krahnclass CommandTransceiver;
1452c1ce244d871c38f48e6bef8af854fa4e7f30c08Darren Krahn"""
146bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn_FUNCTION_DECLARATIONS = """
147bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren KrahnTRUNKS_EXPORT size_t GetNumberOfRequestHandles(TPM_CC command_code);
148bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren KrahnTRUNKS_EXPORT size_t GetNumberOfResponseHandles(TPM_CC command_code);
149bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn"""
150b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn_CLASS_BEGIN = """
151ef87f3e63b93ff722a8cbcee9c54d55d085221a3Darren Krahnclass TRUNKS_EXPORT Tpm {
152b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn public:
1532c1ce244d871c38f48e6bef8af854fa4e7f30c08Darren Krahn  // Does not take ownership of |transceiver|.
154a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  explicit Tpm(CommandTransceiver* transceiver) : transceiver_(transceiver) {}
1552c1ce244d871c38f48e6bef8af854fa4e7f30c08Darren Krahn  virtual ~Tpm() {}
1562c1ce244d871c38f48e6bef8af854fa4e7f30c08Darren Krahn
157b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
158b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn_CLASS_END = """
1592c1ce244d871c38f48e6bef8af854fa4e7f30c08Darren Krahn private:
1602c1ce244d871c38f48e6bef8af854fa4e7f30c08Darren Krahn  CommandTransceiver* transceiver_;
1612c1ce244d871c38f48e6bef8af854fa4e7f30c08Darren Krahn
1622c1ce244d871c38f48e6bef8af854fa4e7f30c08Darren Krahn  DISALLOW_COPY_AND_ASSIGN(Tpm);
163b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn};
164b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
165b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn_SERIALIZE_BASIC_TYPE = """
166e1c5e72731573f043c12a9d0abc40dda839abc4eDarren KrahnTPM_RC Serialize_%(type)s(const %(type)s& value, std::string* buffer) {
1674ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  VLOG(3) << __func__;
168b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  %(type)s value_net = value;
169b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  switch (sizeof(%(type)s)) {
170b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    case 2:
171b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      value_net = base::HostToNet16(value);
172b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      break;
173b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    case 4:
174b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      value_net = base::HostToNet32(value);
175b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      break;
176b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    case 8:
177b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      value_net = base::HostToNet64(value);
178b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      break;
179b0f7d258e26830ebace9876cad07e6aefe8e2780Darren Krahn    default:
180b0f7d258e26830ebace9876cad07e6aefe8e2780Darren Krahn      break;
181b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  }
182b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  const char* value_bytes = reinterpret_cast<const char*>(&value_net);
183b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  buffer->append(value_bytes, sizeof(%(type)s));
184b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  return TPM_RC_SUCCESS;
185b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn}
186b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn
187a0471fe9c5a68344516f5897a1f1c342438e514eDarren KrahnTPM_RC Parse_%(type)s(
188a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    std::string* buffer,
189a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    %(type)s* value,
190a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    std::string* value_bytes) {
1914ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  VLOG(3) << __func__;
192b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  if (buffer->size() < sizeof(%(type)s))
193b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    return TPM_RC_INSUFFICIENT;
194b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  %(type)s value_net = 0;
195b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  memcpy(&value_net, buffer->data(), sizeof(%(type)s));
196b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  switch (sizeof(%(type)s)) {
197b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    case 2:
198b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      *value = base::NetToHost16(value_net);
199b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      break;
200b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    case 4:
201b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      *value = base::NetToHost32(value_net);
202b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      break;
203b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    case 8:
204b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      *value = base::NetToHost64(value_net);
205b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      break;
206b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    default:
207b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      *value = value_net;
208b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  }
209a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  if (value_bytes) {
210a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    value_bytes->append(buffer->substr(0, sizeof(%(type)s)));
211a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  }
212b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  buffer->erase(0, sizeof(%(type)s));
213b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  return TPM_RC_SUCCESS;
214b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn}
215b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
216e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn_SERIALIZE_DECLARATION = """
217ef87f3e63b93ff722a8cbcee9c54d55d085221a3Darren KrahnTRUNKS_EXPORT TPM_RC Serialize_%(type)s(
218e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn    const %(type)s& value,
219e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn    std::string* buffer);
220e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn
221ef87f3e63b93ff722a8cbcee9c54d55d085221a3Darren KrahnTRUNKS_EXPORT TPM_RC Parse_%(type)s(
222e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn    std::string* buffer,
223a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    %(type)s* value,
224a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    std::string* value_bytes);
225e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn"""
22664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
227434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn_SIMPLE_TPM2B_HELPERS_DECLARATION = """
228ef87f3e63b93ff722a8cbcee9c54d55d085221a3Darren KrahnTRUNKS_EXPORT %(type)s Make_%(type)s(
229a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    const std::string& bytes);
230ef87f3e63b93ff722a8cbcee9c54d55d085221a3Darren KrahnTRUNKS_EXPORT std::string StringFrom_%(type)s(
231a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    const %(type)s& tpm2b);
232a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn"""
233434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn_COMPLEX_TPM2B_HELPERS_DECLARATION = """
234ef87f3e63b93ff722a8cbcee9c54d55d085221a3Darren KrahnTRUNKS_EXPORT %(type)s Make_%(type)s(
23567cd0f46faba7d525242330b6f77cf6c90d22734Utkarsh Sanghi    const %(inner_type)s& inner);
236434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn"""
237a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn
238bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn_HANDLE_COUNT_FUNCTION_START = """
239bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahnsize_t GetNumberOf%(handle_type)sHandles(TPM_CC command_code) {
240bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn  switch (command_code) {"""
241bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn_HANDLE_COUNT_FUNCTION_CASE = """
242bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn    case %(command_code)s: return %(handle_count)s;"""
243bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn_HANDLE_COUNT_FUNCTION_END = """
2444ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn    default: LOG(WARNING) << "Unknown command code: " << command_code;
245bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn  }
246bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn  return 0;
247bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn}
248bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn"""
249a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn
250a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahndef FixName(name):
251a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  """Fixes names to conform to Chromium style."""
252434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn  # Handle names with array notation. E.g. 'myVar[10]' is grouped as 'myVar' and
253434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn  # '[10]'.
254a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  match = re.search(r'([^\[]*)(\[.*\])*', name)
255434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn  # Transform the name to Chromium style. E.g. 'myVarAgain' becomes
256434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn  # 'my_var_again'.
257a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  fixed_name = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', match.group(1)).lower()
258a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  return fixed_name + match.group(2) if match.group(2) else fixed_name
259a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn
260a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn
261a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahndef IsTPM2B(name):
262a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  return name.startswith('TPM2B_')
263a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn
26464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
2651aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahndef GetCppBool(condition):
2661aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn  if condition:
2671aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn    return 'true'
2681aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn  return 'false'
2691aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn
2701aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn
27164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahnclass Typedef(object):
27289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  """Represents a TPM typedef.
27389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
27489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  Attributes:
27589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    old_type: The existing type in a typedef statement.
27689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    new_type: The new type in a typedef statement.
27789ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  """
27864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
27964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _TYPEDEF = 'typedef %(old_type)s %(new_type)s;\n'
280b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  _SERIALIZE_FUNCTION = """
281e1c5e72731573f043c12a9d0abc40dda839abc4eDarren KrahnTPM_RC Serialize_%(new)s(
282e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn    const %(new)s& value,
283e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn    std::string* buffer) {
2844ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  VLOG(3) << __func__;
285b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  return Serialize_%(old)s(value, buffer);
286b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn}
287b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
288b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  _PARSE_FUNCTION = """
289e1c5e72731573f043c12a9d0abc40dda839abc4eDarren KrahnTPM_RC Parse_%(new)s(
290e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn    std::string* buffer,
291a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    %(new)s* value,
292a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    std::string* value_bytes) {
2934ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  VLOG(3) << __func__;
294a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  return Parse_%(old)s(buffer, value, value_bytes);
295b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn}
296b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
29764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
29864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def __init__(self, old_type, new_type):
29989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Initializes a Typedef instance.
30089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
30189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Args:
30289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      old_type: The existing type in a typedef statement.
30389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      new_type: The new type in a typedef statement.
30489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
30564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self.old_type = old_type
30664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self.new_type = new_type
30764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
30864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def OutputForward(self, out_file, defined_types, typemap):
30989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Writes a typedef definition to |out_file|.
31089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
31189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Any outstanding dependencies will be forward declared. This method is the
31289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    same as Output() because forward declarations do not apply for typedefs.
31389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
31489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Args:
31589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      out_file: The output file.
31689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      defined_types: A set of types for which definitions have already been
31789ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn          generated.
31889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      typemap: A dict mapping type names to the corresponding object.
31989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
32064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self.Output(out_file, defined_types, typemap)
32164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
32264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def Output(self, out_file, defined_types, typemap):
32364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    """Writes a typedef definition to |out_file|.
32464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
32564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    Any outstanding dependencies will be forward declared.
32664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
32764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    Args:
32864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      out_file: The output file.
32964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      defined_types: A set of types for which definitions have already been
33089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn          generated.
33164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      typemap: A dict mapping type names to the corresponding object.
33264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    """
33364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    if self.new_type in defined_types:
33464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      return
33564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    # Make sure the dependency is already defined.
33664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    if self.old_type not in defined_types:
33764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      typemap[self.old_type].OutputForward(out_file, defined_types, typemap)
33864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    out_file.write(self._TYPEDEF % {'old_type': self.old_type,
33964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn                                    'new_type': self.new_type})
34064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    defined_types.add(self.new_type)
34164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
342b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  def OutputSerialize(self, out_file, serialized_types, typemap):
343b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    """Writes a serialize and parse function for the typedef to |out_file|.
344b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn
345b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    Args:
346b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      out_file: The output file.
347b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      serialized_types: A set of types for which serialize and parse functions
348b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        have already been generated.
349b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      typemap: A dict mapping type names to the corresponding object.
350b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    """
351b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    if self.new_type in serialized_types:
352b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      return
353b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    if self.old_type not in serialized_types:
354b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      typemap[self.old_type].OutputSerialize(out_file, serialized_types,
355b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                                             typemap)
356b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    out_file.write(self._SERIALIZE_FUNCTION % {'old': self.old_type,
357b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                                               'new': self.new_type})
358b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    out_file.write(self._PARSE_FUNCTION % {'old': self.old_type,
359b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                                           'new': self.new_type})
360b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    serialized_types.add(self.new_type)
361b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn
36264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
36364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahnclass Constant(object):
36489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  """Represents a TPM constant.
36589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
36689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  Attributes:
36789ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    const_type: The type of the constant (e.g. 'int').
36889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    name: The name of the constant (e.g. 'kMyConstant').
36989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    value: The value of the constant (e.g. '7').
37089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  """
37164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
37264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _CONSTANT = 'const %(type)s %(name)s = %(value)s;\n'
37364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
37464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def __init__(self, const_type, name, value):
37589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Initializes a Constant instance.
37689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
37789ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Args:
37889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      const_type: The type of the constant (e.g. 'int').
37989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      name: The name of the constant (e.g. 'kMyConstant').
38089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      value: The value of the constant (e.g. '7').
38189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
38264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self.const_type = const_type
38364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self.name = name
38464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self.value = value
38564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
38664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def Output(self, out_file, defined_types, typemap):
38764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    """Writes a constant definition to |out_file|.
38864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
38964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    Any outstanding dependencies will be forward declared.
39064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
39164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    Args:
39264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      out_file: The output file.
39364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      defined_types: A set of types for which definitions have already been
39489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn          generated.
39564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      typemap: A dict mapping type names to the corresponding object.
39664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    """
39764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    # Make sure the dependency is already defined.
39864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    if self.const_type not in defined_types:
39964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      typemap[self.const_type].OutputForward(out_file, defined_types, typemap)
40064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    out_file.write(self._CONSTANT % {'type': self.const_type,
40164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn                                     'name': self.name,
40264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn                                     'value': self.value})
40364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
40464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
40564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahnclass Structure(object):
40689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  """Represents a TPM structure or union.
40789ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
40889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  Attributes:
40989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    name: The name of the structure.
41089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    is_union: A boolean indicating whether this is a union.
41189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    fields: A list of (type, name) tuples representing the struct fields.
41289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    depends_on: A list of strings for types this struct depends on other than
41389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn        field types. See AddDependency() for more details.
41489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  """
41564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
41664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _STRUCTURE = 'struct %(name)s {\n'
41764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _STRUCTURE_FORWARD = 'struct %(name)s;\n'
41864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _UNION = 'union %(name)s {\n'
41964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _UNION_FORWARD = 'union %(name)s;\n'
42064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _STRUCTURE_END = '};\n\n'
42164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _STRUCTURE_FIELD = '  %(type)s %(name)s;\n'
422b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  _SERIALIZE_FUNCTION_START = """
423e1c5e72731573f043c12a9d0abc40dda839abc4eDarren KrahnTPM_RC Serialize_%(type)s(
424e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn    const %(type)s& value,
425e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn    std::string* buffer) {
426b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  TPM_RC result = TPM_RC_SUCCESS;
4274ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  VLOG(3) << __func__;
428b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
429b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  _SERIALIZE_FIELD = """
430b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  result = Serialize_%(type)s(value.%(name)s, buffer);
431b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  if (result) {
432b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    return result;
433b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  }
434b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
435b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  _SERIALIZE_FIELD_ARRAY = """
43658a6ad9e4e634f7dbafaea963ad43076e0ed1733Darren Krahn  if (arraysize(value.%(name)s) < value.%(count)s) {
43758a6ad9e4e634f7dbafaea963ad43076e0ed1733Darren Krahn    return TPM_RC_INSUFFICIENT;
43858a6ad9e4e634f7dbafaea963ad43076e0ed1733Darren Krahn  }
439b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  for (uint32_t i = 0; i < value.%(count)s; ++i) {
440b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    result = Serialize_%(type)s(value.%(name)s[i], buffer);
441b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    if (result) {
442b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      return result;
443b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    }
444b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  }
445b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
446b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  _SERIALIZE_FIELD_WITH_SELECTOR = """
447e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn  result = Serialize_%(type)s(
448e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn      value.%(name)s,
449e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn      value.%(selector_name)s,
450e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn      buffer);
451b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  if (result) {
452b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    return result;
453b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  }
454b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
455434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn  _SERIALIZE_COMPLEX_TPM2B = """
456434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn  std::string field_bytes;
457434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn  result = Serialize_%(type)s(value.%(name)s, &field_bytes);
458434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn  if (result) {
459434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn    return result;
460434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn  }
461434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn  std::string size_bytes;
462434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn  result = Serialize_UINT16(field_bytes.size(), &size_bytes);
463434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn  if (result) {
464434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn    return result;
465434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn  }
466434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn  buffer->append(size_bytes + field_bytes);
467434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn"""
468b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  _PARSE_FUNCTION_START = """
469e1c5e72731573f043c12a9d0abc40dda839abc4eDarren KrahnTPM_RC Parse_%(type)s(
470e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn    std::string* buffer,
471a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    %(type)s* value,
472a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    std::string* value_bytes) {
473b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  TPM_RC result = TPM_RC_SUCCESS;
4744ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  VLOG(3) << __func__;
475b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
476b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  _PARSE_FIELD = """
477a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  result = Parse_%(type)s(
478a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      buffer,
479a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      &value->%(name)s,
480a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      value_bytes);
481b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  if (result) {
482b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    return result;
483b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  }
484b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
485b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  _PARSE_FIELD_ARRAY = """
48658a6ad9e4e634f7dbafaea963ad43076e0ed1733Darren Krahn  if (arraysize(value->%(name)s) < value->%(count)s) {
48758a6ad9e4e634f7dbafaea963ad43076e0ed1733Darren Krahn    return TPM_RC_INSUFFICIENT;
48858a6ad9e4e634f7dbafaea963ad43076e0ed1733Darren Krahn  }
489b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  for (uint32_t i = 0; i < value->%(count)s; ++i) {
490a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    result = Parse_%(type)s(
491a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn        buffer,
492a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn        &value->%(name)s[i],
493a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn        value_bytes);
494b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    if (result) {
495b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      return result;
496b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    }
497b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  }
498b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
499b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  _PARSE_FIELD_WITH_SELECTOR = """
500e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn  result = Parse_%(type)s(
501e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn      buffer,
502e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn      value->%(selector_name)s,
503a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      &value->%(name)s,
504a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      value_bytes);
505b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  if (result) {
506b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    return result;
507b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  }
508b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
509b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  _SERIALIZE_FUNCTION_END = '  return result;\n}\n'
510b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  _ARRAY_FIELD_RE = re.compile(r'(.*)\[(.*)\]')
511b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  _ARRAY_FIELD_SIZE_RE = re.compile(r'^(count|size)')
512b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  _UNION_TYPE_RE = re.compile(r'^TPMU_.*')
513b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  _SERIALIZE_UNION_FUNCTION_START = """
514b49375c15718568c70ebfd55eaee790a2b693944Darren KrahnTPM_RC Serialize_%(union_type)s(
515b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    const %(union_type)s& value,
516b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    %(selector_type)s selector,
517b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    std::string* buffer) {
518b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  TPM_RC result = TPM_RC_SUCCESS;
5194ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  VLOG(3) << __func__;
520b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
521b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  _SERIALIZE_UNION_FIELD = """
522b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  if (selector == %(selector_value)s) {
523b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    result = Serialize_%(field_type)s(value.%(field_name)s, buffer);
524b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    if (result) {
525b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      return result;
526b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    }
527b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  }
528b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
529b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  _SERIALIZE_UNION_FIELD_ARRAY = """
530b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  if (selector == %(selector_value)s) {
53158a6ad9e4e634f7dbafaea963ad43076e0ed1733Darren Krahn    if (arraysize(value.%(field_name)s) < %(count)s) {
53258a6ad9e4e634f7dbafaea963ad43076e0ed1733Darren Krahn      return TPM_RC_INSUFFICIENT;
53358a6ad9e4e634f7dbafaea963ad43076e0ed1733Darren Krahn    }
534b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    for (uint32_t i = 0; i < %(count)s; ++i) {
535b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      result = Serialize_%(field_type)s(value.%(field_name)s[i], buffer);
536b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      if (result) {
537b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        return result;
538b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      }
539b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    }
540b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  }
541b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
542b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  _PARSE_UNION_FUNCTION_START = """
543b49375c15718568c70ebfd55eaee790a2b693944Darren KrahnTPM_RC Parse_%(union_type)s(
544b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    std::string* buffer,
545b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    %(selector_type)s selector,
546a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    %(union_type)s* value,
547a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    std::string* value_bytes) {
548b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  TPM_RC result = TPM_RC_SUCCESS;
5494ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  VLOG(3) << __func__;
550b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
551b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  _PARSE_UNION_FIELD = """
552b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  if (selector == %(selector_value)s) {
553a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    result = Parse_%(field_type)s(
554a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn        buffer,
555a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn        &value->%(field_name)s,
556a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn        value_bytes);
557b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    if (result) {
558b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      return result;
559b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    }
560b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  }
561b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
562b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  _PARSE_UNION_FIELD_ARRAY = """
563b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  if (selector == %(selector_value)s) {
56458a6ad9e4e634f7dbafaea963ad43076e0ed1733Darren Krahn    if (arraysize(value->%(field_name)s) < %(count)s) {
56558a6ad9e4e634f7dbafaea963ad43076e0ed1733Darren Krahn      return TPM_RC_INSUFFICIENT;
56658a6ad9e4e634f7dbafaea963ad43076e0ed1733Darren Krahn    }
567b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    for (uint32_t i = 0; i < %(count)s; ++i) {
568a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      result = Parse_%(field_type)s(
569a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn          buffer,
570a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn          &value->%(field_name)s[i],
571a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn          value_bytes);
572b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      if (result) {
573b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        return result;
574b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      }
575b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    }
576b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  }
577b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
578b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  _EMPTY_UNION_CASE = """
579b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  if (selector == %(selector_value)s) {
580b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    // Do nothing.
581b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  }
582b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn"""
583434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn  _SIMPLE_TPM2B_HELPERS = """
584a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn%(type)s Make_%(type)s(
585a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    const std::string& bytes) {
586a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  %(type)s tpm2b;
587a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  CHECK(bytes.size() <= sizeof(tpm2b.%(buffer_name)s));
588a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  memset(&tpm2b, 0, sizeof(%(type)s));
589a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  tpm2b.size = bytes.size();
590a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  memcpy(tpm2b.%(buffer_name)s, bytes.data(), bytes.size());
591a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  return tpm2b;
592a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn}
593a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn
594a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahnstd::string StringFrom_%(type)s(
595a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    const %(type)s& tpm2b) {
596a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  const char* char_buffer = reinterpret_cast<const char*>(
597a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      tpm2b.%(buffer_name)s);
598a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  return std::string(char_buffer, tpm2b.size);
599a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn}
600a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn"""
601434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn  _COMPLEX_TPM2B_HELPERS = """
602434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn%(type)s Make_%(type)s(
603434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn    const %(inner_type)s& inner) {
604434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn  %(type)s tpm2b;
605434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn  tpm2b.size = sizeof(%(inner_type)s);
606434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn  tpm2b.%(inner_name)s = inner;
607434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn  return tpm2b;
608434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn}
609434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn"""
61064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
61164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def __init__(self, name, is_union):
61289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Initializes a Structure instance.
61389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
61489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Initially the instance will have no fields and no dependencies. Those can be
61589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    added with the AddField() and AddDependency() methods.
61689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
61789ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Args:
61889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      name: The name of the structure.
61989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      is_union: A boolean indicating whether this is a union.
62089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
62164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self.name = name
62264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self.is_union = is_union
62364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self.fields = []
62464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self.depends_on = []
62589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    self._forwarded = False
62664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
627a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  def AddField(self, field_type, field_name):
62889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Adds a field for this struct.
62989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
63089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Args:
63189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      field_type: The type of the field.
63289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      field_name: The name of the field.
63389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
634a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    self.fields.append((field_type, FixName(field_name)))
63564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
63664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def AddDependency(self, required_type):
63764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    """Adds an explicit dependency on another type.
63864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
63964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    This is used in cases where there is an additional dependency other than the
64064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    field types, which are implicit dependencies.  For example, a field like
64164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    FIELD_TYPE value[sizeof(OTHER_TYPE)] would need OTHER_TYPE to be already
64264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    declared.
64364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
64464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    Args:
64564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      required_type: The type this structure depends on.
64664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    """
64764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self.depends_on.append(required_type)
64864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
649434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn  def IsSimpleTPM2B(self):
65089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Returns whether this struct is a TPM2B structure with raw bytes."""
651a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    return self.name.startswith('TPM2B_') and self.fields[1][0] == 'BYTE'
652a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn
653434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn  def IsComplexTPM2B(self):
654434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn    """Returns whether this struct is a TPM2B structure with an inner struct."""
655434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn    return self.name.startswith('TPM2B_') and self.fields[1][0] != 'BYTE'
656434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn
65764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def _GetFieldTypes(self):
65889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Creates a set which holds all current field types.
65989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
66089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Returns:
66189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      A set of field types.
66289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
66364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    return set([field[0] for field in self.fields])
66464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
66564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def OutputForward(self, out_file, unused_defined_types, unused_typemap):
66689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Writes a structure forward declaration to |out_file|.
66789ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
66889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    This method needs to match the OutputForward method in other type classes
66989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    (e.g. Typedef) which is why the unused_* args exist.
67089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
67189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Args:
67289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      out_file: The output file.
67389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      unused_defined_types: Not used.
67489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      unused_typemap: Not used.
67589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
67689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    if self._forwarded:
67764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      return
67864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    if self.is_union:
67964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      out_file.write(self._UNION_FORWARD % {'name': self.name})
68064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    else:
68164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      out_file.write(self._STRUCTURE_FORWARD % {'name': self.name})
68289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    self._forwarded = True
68364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
68464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def Output(self, out_file, defined_types, typemap):
68564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    """Writes a structure definition to |out_file|.
68664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
68764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    Any outstanding dependencies will be defined.
68864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
68964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    Args:
69064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      out_file: The output file.
69164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      defined_types: A set of types for which definitions have already been
69264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        generated.
69364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      typemap: A dict mapping type names to the corresponding object.
69464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    """
69564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    if self.name in defined_types:
69664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      return
69764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    # Make sure any dependencies are already defined.
69864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    for field_type in self._GetFieldTypes():
69964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      if field_type not in defined_types:
70064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        typemap[field_type].Output(out_file, defined_types, typemap)
70164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    for required_type in self.depends_on:
70264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      if required_type not in defined_types:
70364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        typemap[required_type].Output(out_file, defined_types, typemap)
70464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    if self.is_union:
70564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      out_file.write(self._UNION % {'name': self.name})
70664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    else:
70764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      out_file.write(self._STRUCTURE % {'name': self.name})
70864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    for field in self.fields:
70964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      out_file.write(self._STRUCTURE_FIELD % {'type': field[0],
71064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn                                              'name': field[1]})
71164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    out_file.write(self._STRUCTURE_END)
71264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    defined_types.add(self.name)
71364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
714b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  def OutputSerialize(self, out_file, serialized_types, typemap):
715b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    """Writes serialize and parse functions for a structure to |out_file|.
716b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn
717b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    Args:
718b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      out_file: The output file.
719b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      serialized_types: A set of types for which serialize and parse functions
720b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        have already been generated.  This type name of this structure will be
721b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        added on success.
722b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      typemap: A dict mapping type names to the corresponding object.
723b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    """
724b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    if (self.name in serialized_types or
725b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        self.name == 'TPMU_NAME' or
726b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        self.name == 'TPMU_ENCRYPTED_SECRET'):
727b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      return
728b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    # Make sure any dependencies already have serialize functions defined.
729b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    for field_type in self._GetFieldTypes():
730b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      if field_type not in serialized_types:
731b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        typemap[field_type].OutputSerialize(out_file, serialized_types, typemap)
732b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    if self.is_union:
733b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      self._OutputUnionSerialize(out_file)
734b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      serialized_types.add(self.name)
735b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      return
736b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    out_file.write(self._SERIALIZE_FUNCTION_START % {'type': self.name})
737434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn    if self.IsComplexTPM2B():
738434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn      field_type = self.fields[1][0]
739434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn      field_name = self.fields[1][1]
740434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn      out_file.write(self._SERIALIZE_COMPLEX_TPM2B % {'type': field_type,
741434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn                                                      'name': field_name})
742434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn    else:
743434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn      for field in self.fields:
744434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn        if self._ARRAY_FIELD_RE.search(field[1]):
745434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn          self._OutputArrayField(out_file, field, self._SERIALIZE_FIELD_ARRAY)
746434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn        elif self._UNION_TYPE_RE.search(field[0]):
747434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn          self._OutputUnionField(out_file, field,
748434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn                                 self._SERIALIZE_FIELD_WITH_SELECTOR)
749434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn        else:
750434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn          out_file.write(self._SERIALIZE_FIELD % {'type': field[0],
751434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn                                                  'name': field[1]})
752b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    out_file.write(self._SERIALIZE_FUNCTION_END)
753b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    out_file.write(self._PARSE_FUNCTION_START % {'type': self.name})
754b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    for field in self.fields:
755b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      if self._ARRAY_FIELD_RE.search(field[1]):
756b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        self._OutputArrayField(out_file, field, self._PARSE_FIELD_ARRAY)
757b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      elif self._UNION_TYPE_RE.search(field[0]):
758b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        self._OutputUnionField(out_file, field, self._PARSE_FIELD_WITH_SELECTOR)
759b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      else:
760b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        out_file.write(self._PARSE_FIELD % {'type': field[0],
761b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                                            'name': field[1]})
762b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    out_file.write(self._SERIALIZE_FUNCTION_END)
763a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    # If this is a TPM2B structure throw in a few convenience functions.
764434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn    if self.IsSimpleTPM2B():
765a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      field_name = self._ARRAY_FIELD_RE.search(self.fields[1][1]).group(1)
766434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn      out_file.write(self._SIMPLE_TPM2B_HELPERS % {'type': self.name,
767434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn                                                   'buffer_name': field_name})
768434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn    elif self.IsComplexTPM2B():
769434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn      field_type = self.fields[1][0]
770434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn      field_name = self.fields[1][1]
771434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn      out_file.write(self._COMPLEX_TPM2B_HELPERS % {'type': self.name,
772434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn                                                    'inner_type': field_type,
773434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn                                                    'inner_name': field_name})
774b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    serialized_types.add(self.name)
775b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn
776b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  def _OutputUnionSerialize(self, out_file):
777b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    """Writes serialize and parse functions for a union to |out_file|.
778b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn
779b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    This is more complex than the struct case because only one field of the
780b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    union is serialized / parsed based on the value of a selector.  Arrays are
781b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    also handled differently: the full size of the array is serialized instead
782b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    of looking for a field which specifies the count.
783b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn
784b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    Args:
785b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      out_file: The output file
786b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    """
787b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    selector_type = union_selectors.GetUnionSelectorType(self.name)
788b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    selector_values = union_selectors.GetUnionSelectorValues(self.name)
789b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    field_types = {f[1]: f[0] for f in self.fields}
790b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    out_file.write(self._SERIALIZE_UNION_FUNCTION_START %
791b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                   {'union_type': self.name, 'selector_type': selector_type})
792b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    for selector in selector_values:
793a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      field_name = FixName(union_selectors.GetUnionSelectorField(self.name,
794a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                                                                 selector))
795b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      if not field_name:
796b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        out_file.write(self._EMPTY_UNION_CASE % {'selector_value': selector})
797b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        continue
798b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      field_type = field_types[field_name]
799b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      array_match = self._ARRAY_FIELD_RE.search(field_name)
800b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      if array_match:
801b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        field_name = array_match.group(1)
802b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        count = array_match.group(2)
803b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        out_file.write(self._SERIALIZE_UNION_FIELD_ARRAY %
804b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                       {'selector_value': selector,
805b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                        'count': count,
806b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                        'field_type': field_type,
807b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                        'field_name': field_name})
808b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      else:
809b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        out_file.write(self._SERIALIZE_UNION_FIELD %
810b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                       {'selector_value': selector,
811b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                        'field_type': field_type,
812b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                        'field_name': field_name})
813b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    out_file.write(self._SERIALIZE_FUNCTION_END)
814b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    out_file.write(self._PARSE_UNION_FUNCTION_START %
815b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                   {'union_type': self.name, 'selector_type': selector_type})
816b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    for selector in selector_values:
817a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      field_name = FixName(union_selectors.GetUnionSelectorField(self.name,
818a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                                                                 selector))
819b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      if not field_name:
820b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        out_file.write(self._EMPTY_UNION_CASE % {'selector_value': selector})
821b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        continue
822b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      field_type = field_types[field_name]
823b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      array_match = self._ARRAY_FIELD_RE.search(field_name)
824b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      if array_match:
825b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        field_name = array_match.group(1)
826b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        count = array_match.group(2)
827b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        out_file.write(self._PARSE_UNION_FIELD_ARRAY %
828b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                       {'selector_value': selector,
829b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                        'count': count,
830b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                        'field_type': field_type,
831b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                        'field_name': field_name})
832b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      else:
833b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        out_file.write(self._PARSE_UNION_FIELD %
834b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                       {'selector_value': selector,
835b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                        'field_type': field_type,
836b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                        'field_name': field_name})
837b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    out_file.write(self._SERIALIZE_FUNCTION_END)
838b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn
839b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  def _OutputUnionField(self, out_file, field, code_format):
840b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    """Writes serialize / parse code for a union field.
841b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn
842b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    In this case |self| may not necessarily represent a union but |field| does.
843b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    This requires that a field of an acceptable selector type appear somewhere
844b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    in the struct.  The value of this field is used as the selector value when
845b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    calling the serialize / parse function for the union.
846b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn
847b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    Args:
848b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      out_file: The output file.
849b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      field: The union field to be processed as a (type, name) tuple.
850b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      code_format: Must be (_SERIALIZE|_PARSE)_FIELD_WITH_SELECTOR
851b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    """
852b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    selector_types = union_selectors.GetUnionSelectorTypes(field[0])
853b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    selector_name = ''
854b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    for tmp in self.fields:
855b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      if tmp[0] in selector_types:
856b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        selector_name = tmp[1]
857b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        break
858b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    assert selector_name, 'Missing selector for %s in %s!' % (field[1],
859b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                                                              self.name)
860b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    out_file.write(code_format % {'type': field[0],
861b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                                  'selector_name': selector_name,
862b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                                  'name': field[1]})
863b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn
864b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  def _OutputArrayField(self, out_file, field, code_format):
865b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    """Writes serialize / parse code for an array field.
866b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn
867b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    The allocated size of the array is ignored and a field which holds the
868b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    actual count of items in the array must exist.  Only the number of items
869b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    represented by the value of that count field are serialized / parsed.
870b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn
871b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    Args:
872b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      out_file: The output file.
873b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      field: The array field to be processed as a (type, name) tuple.
874b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      code_format: Must be (_SERIALIZE|_PARSE)_FIELD_ARRAY
875b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    """
876b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    field_name = self._ARRAY_FIELD_RE.search(field[1]).group(1)
877b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    for count_field in self.fields:
878b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      assert count_field != field, ('Missing count field for %s in %s!' %
879b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                                    (field[1], self.name))
880b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn      if self._ARRAY_FIELD_SIZE_RE.search(count_field[1]):
881b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        out_file.write(code_format % {'count': count_field[1],
882b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                                      'type': field[0],
883b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn                                      'name': field_name})
884b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn        break
885b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn
88664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
88764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahnclass Define(object):
88889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  """Represents a preprocessor define.
88989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
89089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  Attributes:
89189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    name: The name being defined.
89289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    value: The value being assigned to the name.
89389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  """
89464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
89564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _DEFINE = '#if !defined(%(name)s)\n#define %(name)s %(value)s\n#endif\n'
89664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
89764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def __init__(self, name, value):
89889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Initializes a Define instance.
89989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
90089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Args:
90189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      name: The name being defined.
90289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      value: The value being assigned to the name.
90389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
90464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self.name = name
90564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self.value = value
90664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
90764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def Output(self, out_file):
90889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Writes a preprocessor define to |out_file|.
90989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
91089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Args:
91189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      out_file: The output file.
91289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
91364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    out_file.write(self._DEFINE % {'name': self.name, 'value': self.value})
91464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
91564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
91664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahnclass StructureParser(object):
91764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  """Structure definition parser.
91864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
91964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  The input text file is extracted from the PDF file containing the TPM
92064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  structures specification from the Trusted Computing Group. The syntax
92164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  of the text file is defined by extract_structures.sh.
92264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
92364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  - Parses typedefs to a list of Typedef objects.
92464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  - Parses constants to a list of Constant objects.
92564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  - Parses structs and unions to a list of Structure objects.
92664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  - Parses defines to a list of Define objects.
92764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
92864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  The parser also creates 'typemap' dict which maps every type to its generator
92964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  object.  This typemap helps manage type dependencies.
93089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
93189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  Example usage:
93289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  parser = StructureParser(open('myfile'))
93389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  types, constants, structs, defines, typemap = parser.Parse()
93464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  """
93564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
93664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  # Compile regular expressions.
93789ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  _BEGIN_TYPES_TOKEN = '_BEGIN_TYPES'
93889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  _BEGIN_CONSTANTS_TOKEN = '_BEGIN_CONSTANTS'
93989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  _BEGIN_STRUCTURES_TOKEN = '_BEGIN_STRUCTURES'
94089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  _BEGIN_UNIONS_TOKEN = '_BEGIN_UNIONS'
94189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  _BEGIN_DEFINES_TOKEN = '_BEGIN_DEFINES'
94289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  _END_TOKEN = '_END'
94364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _OLD_TYPE_RE = re.compile(r'^_OLD_TYPE\s+(\w+)$')
94464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _NEW_TYPE_RE = re.compile(r'^_NEW_TYPE\s+(\w+)$')
94564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _CONSTANTS_SECTION_RE = re.compile(r'^_CONSTANTS.* (\w+)$')
94664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _STRUCTURE_SECTION_RE = re.compile(r'^_STRUCTURE\s+(\w+)$')
94764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _UNION_SECTION_RE = re.compile(r'^_UNION\s+(\w+)$')
94864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _TYPE_RE = re.compile(r'^_TYPE\s+(\w+)$')
94964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _NAME_RE = re.compile(r'^_NAME\s+([a-zA-Z0-9_()\[\]/\*\+\-]+)$')
95064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _VALUE_RE = re.compile(r'^_VALUE\s+(.+)$')
95164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _SIZEOF_RE = re.compile(r'^.*sizeof\(([a-zA-Z0-9_]*)\).*$')
95264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
95364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def __init__(self, in_file):
95489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Initializes a StructureParser instance.
95589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
95689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Args:
95789ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      in_file: A file as returned by open() which has been opened for reading.
95889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
95964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self._line = None
96064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self._in_file = in_file
96164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
96264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def _NextLine(self):
96389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Gets the next input line.
96489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
96589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Returns:
96689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      The next input line if another line is available, None otherwise.
96789ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
96864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    try:
96964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      self._line = self._in_file.next()
97064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    except StopIteration:
97164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      self._line = None
97264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
97364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def Parse(self):
97464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    """Parse everything in a structures file.
97564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
97664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    Returns:
97764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      Lists of objects and a type-map as described in the class documentation.
97864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      Returns these in the following order: types, constants, structs, defines,
97964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      typemap.
98064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    """
98164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self._NextLine()
98264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    types = []
98364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    constants = []
98464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    structs = []
98564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    defines = []
98664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    typemap = {}
98764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    while self._line:
98889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      if self._BEGIN_TYPES_TOKEN == self._line.rstrip():
98964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        types += self._ParseTypes(typemap)
99089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      elif self._BEGIN_CONSTANTS_TOKEN == self._line.rstrip():
99164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        constants += self._ParseConstants(types, typemap)
99289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      elif self._BEGIN_STRUCTURES_TOKEN == self._line.rstrip():
99364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        structs += self._ParseStructures(self._STRUCTURE_SECTION_RE, typemap)
99489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      elif self._BEGIN_UNIONS_TOKEN == self._line.rstrip():
99564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        structs += self._ParseStructures(self._UNION_SECTION_RE, typemap)
99689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      elif self._BEGIN_DEFINES_TOKEN == self._line.rstrip():
99764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        defines += self._ParseDefines()
99864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      else:
99989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn        print('Invalid file format: %s' % self._line)
100064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        break
100164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      self._NextLine()
100264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    # Empty structs not handled by the extractor.
100364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self._AddEmptyStruct('TPMU_SYM_DETAILS', True, structs, typemap)
100464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    # Defines which are used in TPM 2.0 Part 2 but not defined there.
100564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    defines.append(Define(
100664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        'MAX_CAP_DATA', '(MAX_CAP_BUFFER-sizeof(TPM_CAP)-sizeof(UINT32))'))
100764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    defines.append(Define(
100864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        'MAX_CAP_ALGS', '(TPM_ALG_LAST - TPM_ALG_FIRST + 1)'))
100964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    defines.append(Define(
101064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        'MAX_CAP_HANDLES', '(MAX_CAP_DATA/sizeof(TPM_HANDLE))'))
101164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    defines.append(Define(
101264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        'MAX_CAP_CC', '((TPM_CC_LAST - TPM_CC_FIRST) + 1)'))
101364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    defines.append(Define(
101464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        'MAX_TPM_PROPERTIES', '(MAX_CAP_DATA/sizeof(TPMS_TAGGED_PROPERTY))'))
101564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    defines.append(Define(
101664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        'MAX_PCR_PROPERTIES', '(MAX_CAP_DATA/sizeof(TPMS_TAGGED_PCR_SELECT))'))
101764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    defines.append(Define(
101864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        'MAX_ECC_CURVES', '(MAX_CAP_DATA/sizeof(TPM_ECC_CURVE))'))
101964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    defines.append(Define('HASH_COUNT', '3'))
102064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    return types, constants, structs, defines, typemap
102164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
102264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def _AddEmptyStruct(self, name, is_union, structs, typemap):
102389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Adds an empty Structure object to |structs| and |typemap|.
102489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
102589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Args:
102689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      name: The name to assign the new structure.
102789ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      is_union: A boolean indicating whether the new structure is a union.
102889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      structs: A list of structures to which the new object is appended.
102989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      typemap: A map of type names to objects to which the new name and object
103089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn          are added.
103189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
103264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    s = Structure(name, is_union)
103364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    structs.append(s)
103464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    typemap[name] = s
103564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    return
103664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
103764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def _ParseTypes(self, typemap):
103864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    """Parses a typedefs section.
103964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
104064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    The current line should be _BEGIN_TYPES and the method will stop parsing
104164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    when an _END line is found.
104264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
104364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    Args:
104464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      typemap: A dictionary to which parsed types are added.
104564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
104664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    Returns:
104764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      A list of Typedef objects.
104864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    """
104964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    types = []
105064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self._NextLine()
105189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    while self._END_TOKEN != self._line.rstrip():
105264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      match = self._OLD_TYPE_RE.search(self._line)
105364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      if not match:
105489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn        print('Invalid old type: %s' % self._line)
105564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        return types
105664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      old_type = match.group(1)
105764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      self._NextLine()
105864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      match = self._NEW_TYPE_RE.search(self._line)
105964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      if not match:
106089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn        print('Invalid new type: %s' % self._line)
106164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        return types
106264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      new_type = match.group(1)
106364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      t = Typedef(old_type, new_type)
106464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      types.append(t)
106564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      typemap[new_type] = t
106664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      self._NextLine()
106764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    return types
106864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
106964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def _ParseConstants(self, types, typemap):
107064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    """Parses a constants section.
107164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
107264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    The current line should be _BEGIN_CONSTANTS and the method will stop parsing
107389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    when an _END line is found. Each group of constants has an associated type
107489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    alias. A Typedef object is created for each of these aliases and added to
107589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    both |types| and |typemap|.
107664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
107764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    Args:
107889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      types: A list of Typedef objects.
107964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      typemap: A dictionary to which parsed types are added.
108064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
108164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    Returns:
108264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      A list of Constant objects.
108364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    """
108464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    constants = []
108564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self._NextLine()
108689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    while self._END_TOKEN != self._line.rstrip():
108764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      match = self._CONSTANTS_SECTION_RE.search(self._line)
108864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      if not match:
108989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn        print('Invalid constants section: %s' % self._line)
109064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        return constants
109164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      constant_typename = match.group(1)
109264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      self._NextLine()
109364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      match = self._TYPE_RE.search(self._line)
109464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      if not match:
109589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn        print('Invalid constants type: %s' % self._line)
109664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        return constants
109764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      constant_type = match.group(1)
109864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      # Create a typedef for the constant group name (e.g. TPM_RC).
109964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      typedef = Typedef(constant_type, constant_typename)
110064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      typemap[constant_typename] = typedef
110164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      types.append(typedef)
110264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      self._NextLine()
110364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      match = self._NAME_RE.search(self._line)
110464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      if not match:
110589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn        print('Invalid constant name: %s' % self._line)
110664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        return constants
110764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      while match:
110864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        name = match.group(1)
110964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        self._NextLine()
111064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        match = self._VALUE_RE.search(self._line)
111164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        if not match:
111289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn          print('Invalid constant value: %s' % self._line)
111364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn          return constants
111464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        value = match.group(1)
111564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        constants.append(Constant(constant_typename, name, value))
111664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        self._NextLine()
111764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        match = self._NAME_RE.search(self._line)
111864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    return constants
111964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
112064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def _ParseStructures(self, section_re, typemap):
112189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Parses structures and unions.
112264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
112364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    The current line should be _BEGIN_STRUCTURES or _BEGIN_UNIONS and the method
112464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    will stop parsing when an _END line is found.
112564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
112664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    Args:
112764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      section_re: The regular expression to use for matching section tokens.
112864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      typemap: A dictionary to which parsed types are added.
112964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
113064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    Returns:
113164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      A list of Structure objects.
113264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    """
113364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    structures = []
113464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    is_union = section_re == self._UNION_SECTION_RE
113564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self._NextLine()
113689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    while self._END_TOKEN != self._line.rstrip():
113764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      match = section_re.search(self._line)
113864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      if not match:
113989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn        print('Invalid structure section: %s' % self._line)
114064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        return structures
114189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      current_structure_name = match.group(1)
114289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      current_structure = Structure(current_structure_name, is_union)
114364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      self._NextLine()
114464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      match = self._TYPE_RE.search(self._line)
114564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      if not match:
114689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn        print('Invalid field type: %s' % self._line)
114764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        return structures
114864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      while match:
114964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        field_type = match.group(1)
115064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        self._NextLine()
115164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        match = self._NAME_RE.search(self._line)
115264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        if not match:
115389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn          print('Invalid field name: %s' % self._line)
115464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn          return structures
115564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        field_name = match.group(1)
115664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        # If the field name includes 'sizeof(SOME_TYPE)', record the dependency
115764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        # on SOME_TYPE.
115864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        match = self._SIZEOF_RE.search(field_name)
115964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        if match:
116064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn          current_structure.AddDependency(match.group(1))
116164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        # Manually change unfortunate names.
116264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        if field_name == 'xor':
116364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn          field_name = 'xor_'
116464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        current_structure.AddField(field_type, field_name)
116564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        self._NextLine()
116664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        match = self._TYPE_RE.search(self._line)
116764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      structures.append(current_structure)
116889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      typemap[current_structure_name] = current_structure
116964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    return structures
117064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
117164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def _ParseDefines(self):
117264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    """Parses preprocessor defines.
117364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
117464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    The current line should be _BEGIN_DEFINES and the method will stop parsing
117564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    when an _END line is found.
117664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
117764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    Returns:
117864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      A list of Define objects.
117964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    """
118064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    defines = []
118164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self._NextLine()
118289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    while self._END_TOKEN != self._line.rstrip():
118364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      match = self._NAME_RE.search(self._line)
118464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      if not match:
118589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn        print('Invalid name: %s' % self._line)
118664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        return defines
118764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      name = match.group(1)
118864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      self._NextLine()
118964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      match = self._VALUE_RE.search(self._line)
119064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      if not match:
119189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn        print('Invalid value: %s' % self._line)
119264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        return defines
119364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      value = match.group(1)
119464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      defines.append(Define(name, value))
119564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      self._NextLine()
119664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    return defines
119764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
119864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
119964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahnclass Command(object):
120089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  """Represents a TPM command.
120189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
120289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  Attributes:
120389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    name: The command name (e.g. 'TPM2_Startup').
120489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    command_code: The name of the command code constant (e.g. TPM2_CC_Startup).
120589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    request_args: A list to hold command input arguments. Each element is a dict
120689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn        and has these keys:
120789ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn            'type': The argument type.
120889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn            'name': The argument name.
120989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn            'command_code': The optional value of the command code constant.
121089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn            'description': Optional descriptive text for the argument.
121189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    response_args: A list identical in form to request_args but to hold command
121289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn        output arguments.
121389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  """
121464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
1215a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  _HANDLE_RE = re.compile(r'TPMI_.H_.*')
12166a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  _CALLBACK_ARG = """
1217e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn      const %(method_name)sResponse& callback"""
12186a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  _DELEGATE_ARG = """
12196a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      AuthorizationDelegate* authorization_delegate"""
12206a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  _SERIALIZE_ARG = """
12216a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      std::string* serialized_command"""
12226a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  _PARSE_ARG = """
12236a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      const std::string& response"""
12246a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  _SERIALIZE_FUNCTION_START = """
12256a5f9fd320f2bd202653d09bad15a75474d49360Darren KrahnTPM_RC Tpm::SerializeCommand_%(method_name)s(%(method_args)s) {
12264ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  VLOG(3) << __func__;
1227a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  TPM_RC rc = TPM_RC_SUCCESS;
1228a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  TPMI_ST_COMMAND_TAG tag = TPM_ST_NO_SESSIONS;
1229a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  UINT32 command_size = 10;  // Header size.
1230a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  std::string handle_section_bytes;
1231a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  std::string parameter_section_bytes;"""
1232a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  _DECLARE_COMMAND_CODE = """
1233a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  TPM_CC command_code = %(command_code)s;"""
12341aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn  _DECLARE_BOOLEAN = """
12351aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn  bool %(var_name)s = %(value)s;"""
1236a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  _SERIALIZE_LOCAL_VAR = """
1237a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  std::string %(var_name)s_bytes;
1238a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  rc = Serialize_%(var_type)s(
1239a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      %(var_name)s,
1240a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      &%(var_name)s_bytes);
1241a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  if (rc != TPM_RC_SUCCESS) {
12426a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    return rc;
1243a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  }"""
1244a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  _ENCRYPT_PARAMETER = """
12458f8c6677db635f52d605e16115db443d85310277Darren Krahn  if (authorization_delegate) {
12468f8c6677db635f52d605e16115db443d85310277Darren Krahn    // Encrypt just the parameter data, not the size.
12478f8c6677db635f52d605e16115db443d85310277Darren Krahn    std::string tmp = %(var_name)s_bytes.substr(2);
12488f8c6677db635f52d605e16115db443d85310277Darren Krahn    if (!authorization_delegate->EncryptCommandParameter(&tmp)) {
12498f8c6677db635f52d605e16115db443d85310277Darren Krahn      return TRUNKS_RC_ENCRYPTION_FAILED;
12508f8c6677db635f52d605e16115db443d85310277Darren Krahn    }
12518f8c6677db635f52d605e16115db443d85310277Darren Krahn    %(var_name)s_bytes.replace(2, std::string::npos, tmp);
12528f8c6677db635f52d605e16115db443d85310277Darren Krahn  }"""
1253a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  _HASH_START = """
1254a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  scoped_ptr<crypto::SecureHash> hash(crypto::SecureHash::Create(
1255a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      crypto::SecureHash::SHA256));"""
1256a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  _HASH_UPDATE = """
1257a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  hash->Update(%(var_name)s.data(),
1258a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn               %(var_name)s.size());"""
1259a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  _APPEND_COMMAND_HANDLE = """
1260a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  handle_section_bytes += %(var_name)s_bytes;
1261a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  command_size += %(var_name)s_bytes.size();"""
1262a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  _APPEND_COMMAND_PARAMETER = """
1263a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  parameter_section_bytes += %(var_name)s_bytes;
1264a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  command_size += %(var_name)s_bytes.size();"""
1265a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  _AUTHORIZE_COMMAND = """
1266a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  std::string command_hash(32, 0);
1267a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  hash->Finish(string_as_array(&command_hash), command_hash.size());
1268a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  std::string authorization_section_bytes;
1269a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  std::string authorization_size_bytes;
12708f8c6677db635f52d605e16115db443d85310277Darren Krahn  if (authorization_delegate) {
12718f8c6677db635f52d605e16115db443d85310277Darren Krahn    if (!authorization_delegate->GetCommandAuthorization(
12728f8c6677db635f52d605e16115db443d85310277Darren Krahn        command_hash,
12731aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn        is_command_parameter_encryption_possible,
12741aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn        is_response_parameter_encryption_possible,
12758f8c6677db635f52d605e16115db443d85310277Darren Krahn        &authorization_section_bytes)) {
12768f8c6677db635f52d605e16115db443d85310277Darren Krahn      return TRUNKS_RC_AUTHORIZATION_FAILED;
12778f8c6677db635f52d605e16115db443d85310277Darren Krahn    }
12788f8c6677db635f52d605e16115db443d85310277Darren Krahn    if (!authorization_section_bytes.empty()) {
12798f8c6677db635f52d605e16115db443d85310277Darren Krahn      tag = TPM_ST_SESSIONS;
12808f8c6677db635f52d605e16115db443d85310277Darren Krahn      std::string tmp;
12818f8c6677db635f52d605e16115db443d85310277Darren Krahn      rc = Serialize_UINT32(authorization_section_bytes.size(),
12828f8c6677db635f52d605e16115db443d85310277Darren Krahn                            &authorization_size_bytes);
12838f8c6677db635f52d605e16115db443d85310277Darren Krahn      if (rc != TPM_RC_SUCCESS) {
12848f8c6677db635f52d605e16115db443d85310277Darren Krahn        return rc;
12858f8c6677db635f52d605e16115db443d85310277Darren Krahn      }
12868f8c6677db635f52d605e16115db443d85310277Darren Krahn      command_size += authorization_size_bytes.size() +
12878f8c6677db635f52d605e16115db443d85310277Darren Krahn                      authorization_section_bytes.size();
1288a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    }
1289a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  }"""
12906a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  _SERIALIZE_FUNCTION_END = """
12916a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  *serialized_command = tag_bytes +
1292a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                        command_size_bytes +
1293a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                        command_code_bytes +
1294a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                        handle_section_bytes +
1295a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                        authorization_size_bytes +
1296a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                        authorization_section_bytes +
1297a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                        parameter_section_bytes;
12986a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  CHECK(serialized_command->size() == command_size) << "Command size mismatch!";
12994ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  VLOG(2) << "Command: " << base::HexEncode(serialized_command->data(),
130003d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn                                            serialized_command->size());
13016a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  return TPM_RC_SUCCESS;
1302a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn}
1303a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn"""
1304a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  _RESPONSE_PARSER_START = """
13056a5f9fd320f2bd202653d09bad15a75474d49360Darren KrahnTPM_RC Tpm::ParseResponse_%(method_name)s(%(method_args)s) {
13064ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  VLOG(3) << __func__;
13074ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  VLOG(2) << "Response: " << base::HexEncode(response.data(), response.size());
1308a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  TPM_RC rc = TPM_RC_SUCCESS;
1309a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  std::string buffer(response);"""
1310a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  _PARSE_LOCAL_VAR = """
1311a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  %(var_type)s %(var_name)s;
1312a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  std::string %(var_name)s_bytes;
1313a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  rc = Parse_%(var_type)s(
1314a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      &buffer,
1315a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      &%(var_name)s,
1316a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      &%(var_name)s_bytes);
1317a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  if (rc != TPM_RC_SUCCESS) {
13186a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    return rc;
13196a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  }"""
13206a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  _PARSE_ARG_VAR = """
13216a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  std::string %(var_name)s_bytes;
13226a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  rc = Parse_%(var_type)s(
13236a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      &buffer,
13246a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      %(var_name)s,
13256a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      &%(var_name)s_bytes);
13266a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  if (rc != TPM_RC_SUCCESS) {
13276a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    return rc;
1328a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  }"""
1329a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  _RESPONSE_ERROR_CHECK = """
1330a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  if (response_size != response.size()) {
13316a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    return TPM_RC_SIZE;
1332a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  }
1333a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  if (response_code != TPM_RC_SUCCESS) {
13346a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    return response_code;
1335a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  }"""
1336a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  _RESPONSE_SECTION_SPLIT = """
1337a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  std::string authorization_section_bytes;
1338a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  if (tag == TPM_ST_SESSIONS) {
1339a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    UINT32 parameter_section_size = buffer.size();
1340c04decde2a6e9b74395f402818852e752534254bUtkarsh Sanghi    rc = Parse_UINT32(&buffer, &parameter_section_size, nullptr);
1341a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    if (rc != TPM_RC_SUCCESS) {
13426a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      return rc;
1343a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    }
1344a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    if (parameter_section_size > buffer.size()) {
13456a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      return TPM_RC_INSUFFICIENT;
1346a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    }
1347a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    authorization_section_bytes = buffer.substr(parameter_section_size);
1348a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    // Keep the parameter section in |buffer|.
1349a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    buffer.erase(parameter_section_size);
1350a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  }"""
1351a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  _AUTHORIZE_RESPONSE = """
1352a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  std::string response_hash(32, 0);
1353a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  hash->Finish(string_as_array(&response_hash), response_hash.size());
1354a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  if (tag == TPM_ST_SESSIONS) {
13558f8c6677db635f52d605e16115db443d85310277Darren Krahn    CHECK(authorization_delegate) << "Authorization delegate missing!";
1356a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    if (!authorization_delegate->CheckResponseAuthorization(
1357a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn        response_hash,
1358a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn        authorization_section_bytes)) {
13596a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      return TRUNKS_RC_AUTHORIZATION_FAILED;
1360a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    }
1361a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  }"""
1362a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  _DECRYPT_PARAMETER = """
1363a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  if (tag == TPM_ST_SESSIONS) {
13648f8c6677db635f52d605e16115db443d85310277Darren Krahn    CHECK(authorization_delegate) << "Authorization delegate missing!";
1365a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    // Decrypt just the parameter data, not the size.
1366a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    std::string tmp = %(var_name)s_bytes.substr(2);
1367a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    if (!authorization_delegate->DecryptResponseParameter(&tmp)) {
13686a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      return TRUNKS_RC_ENCRYPTION_FAILED;
1369a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    }
1370a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    %(var_name)s_bytes.replace(2, std::string::npos, tmp);
1371a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    rc = Parse_%(var_type)s(
1372a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn        &%(var_name)s_bytes,
13736a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn        %(var_name)s,
1374c04decde2a6e9b74395f402818852e752534254bUtkarsh Sanghi        nullptr);
1375a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    if (rc != TPM_RC_SUCCESS) {
13766a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      return rc;
1377a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    }
1378a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  }"""
1379a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  _RESPONSE_PARSER_END = """
13806a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  return TPM_RC_SUCCESS;
13816a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn}
13826a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn"""
13836a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  _ERROR_CALLBACK_START = """
13846a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahnvoid %(method_name)sErrorCallback(
13856a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    const Tpm::%(method_name)sResponse& callback,
13866a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    TPM_RC response_code) {
13874ede7fcc1571b23867536b2506900fc3987c2dd5Darren Krahn  VLOG(1) << __func__;
13886a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  callback.Run(response_code"""
13896a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  _ERROR_CALLBACK_ARG = """,
13906a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn               %(arg_type)s()"""
13916a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  _ERROR_CALLBACK_END = """);
13926a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn}
13936a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn"""
13946a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  _RESPONSE_CALLBACK_START = """
13956a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahnvoid %(method_name)sResponseParser(
13966a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    const Tpm::%(method_name)sResponse& callback,
13976a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    AuthorizationDelegate* authorization_delegate,
13986a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    const std::string& response) {
139903d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn  VLOG(1) << __func__;
14006a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  base::Callback<void(TPM_RC)> error_reporter =
14016a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      base::Bind(%(method_name)sErrorCallback, callback);"""
14026a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  _DECLARE_ARG_VAR = """
14036a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  %(var_type)s %(var_name)s;"""
14046a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  _RESPONSE_CALLBACK_END = """
14056a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  TPM_RC rc = Tpm::ParseResponse_%(method_name)s(
14066a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      response,%(method_arg_names_out)s
14076a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      authorization_delegate);
14086a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  if (rc != TPM_RC_SUCCESS) {
14096a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    error_reporter.Run(rc);
14106a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    return;
14116a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  }
14126a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  callback.Run(
14136a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      rc%(method_arg_names_in)s);
14146a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn}
14156a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn"""
14166a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  _ASYNC_METHOD = """
14176a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahnvoid Tpm::%(method_name)s(%(method_args)s) {
141803d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn  VLOG(1) << __func__;
14196a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  base::Callback<void(TPM_RC)> error_reporter =
14206a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      base::Bind(%(method_name)sErrorCallback, callback);
14216a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  base::Callback<void(const std::string&)> parser =
14226a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      base::Bind(%(method_name)sResponseParser,
14236a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn                 callback,
14246a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn                 authorization_delegate);
14256a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  std::string command;
14266a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  TPM_RC rc = SerializeCommand_%(method_name)s(%(method_arg_names)s
14276a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      &command,
14286a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      authorization_delegate);
14296a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  if (rc != TPM_RC_SUCCESS) {
14306a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    error_reporter.Run(rc);
14316a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    return;
14326a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  }
14336a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  transceiver_->SendCommand(command, parser);
14346a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn}
14356a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn"""
14366a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  _SYNC_METHOD = """
14376a5f9fd320f2bd202653d09bad15a75474d49360Darren KrahnTPM_RC Tpm::%(method_name)sSync(%(method_args)s) {
143803d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn  VLOG(1) << __func__;
14396a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  std::string command;
14406a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  TPM_RC rc = SerializeCommand_%(method_name)s(%(method_arg_names_in)s
14416a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      &command,
14426a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      authorization_delegate);
14436a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  if (rc != TPM_RC_SUCCESS) {
14446a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    return rc;
14456a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  }
144680c739e10fd606b24e2656cad6e566c66bb218d4Darren Krahn  std::string response = transceiver_->SendCommandAndWait(command);
14476a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  rc = ParseResponse_%(method_name)s(
14486a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      response,%(method_arg_names_out)s
14496a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      authorization_delegate);
14506a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  return rc;
1451a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn}
1452a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn"""
1453e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn
145464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def __init__(self, name):
145589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Initializes a Command instance.
145689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
145789ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Initially the request_args and response_args attributes are not set.
145889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
145989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Args:
146089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      name: The command name (e.g. 'TPM2_Startup').
146189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
146264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self.name = name
146364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self.command_code = ''
146464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self.request_args = None
146564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self.response_args = None
146664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
146764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def OutputDeclarations(self, out_file):
146889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Prints method and callback declaration statements for this command.
1469a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn
1470a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    Args:
147189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      out_file: The output file.
1472a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    """
147364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self._OutputCallbackSignature(out_file)
14746a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    self._OutputMethodSignatures(out_file)
147564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
14766a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  def OutputSerializeFunction(self, out_file):
14776a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    """Generates a serialize function for the command inputs.
1478a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn
1479a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    Args:
1480a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      out_file: Generated code is written to this file.
1481a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    """
1482a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    # Categorize arguments as either handles or parameters.
1483a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    handles, parameters = self._SplitArgs(self.request_args)
14841aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn    response_parameters = self._SplitArgs(self.response_args)[1]
14851aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn    out_file.write(self._SERIALIZE_FUNCTION_START % {
14861aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn        'method_name': self._MethodName(),
14871aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn        'method_args': self._SerializeArgs()})
1488a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    out_file.write(self._DECLARE_COMMAND_CODE % {'command_code':
1489a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                                                 self.command_code})
14901aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn    out_file.write(self._DECLARE_BOOLEAN % {
14911aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn        'var_name': 'is_command_parameter_encryption_possible',
14921aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn        'value': GetCppBool(parameters and IsTPM2B(parameters[0]['type']))})
14931aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn    out_file.write(self._DECLARE_BOOLEAN % {
14941aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn        'var_name': 'is_response_parameter_encryption_possible',
14951aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn        'value': GetCppBool(response_parameters and
14961aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn                            IsTPM2B(response_parameters[0]['type']))})
1497a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    # Serialize the command code and all the handles and parameters.
1498a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    out_file.write(self._SERIALIZE_LOCAL_VAR % {'var_name': 'command_code',
1499a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                                                'var_type': 'TPM_CC'})
1500a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    for arg in self.request_args:
1501a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      out_file.write(self._SERIALIZE_LOCAL_VAR % {'var_name': arg['name'],
1502a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                                                  'var_type': arg['type']})
1503a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    # Encrypt the first parameter (before doing authorization) if necessary.
1504a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    if parameters and IsTPM2B(parameters[0]['type']):
1505a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      out_file.write(self._ENCRYPT_PARAMETER % {'var_name':
1506a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                                                parameters[0]['name']})
1507a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    # Compute the command hash and construct handle and parameter sections.
1508a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    out_file.write(self._HASH_START)
1509a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    out_file.write(self._HASH_UPDATE % {'var_name': 'command_code_bytes'})
1510a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    for handle in handles:
1511a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      out_file.write(self._HASH_UPDATE % {'var_name':
1512a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                                          '%s_name' % handle['name']})
1513a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      out_file.write(self._APPEND_COMMAND_HANDLE % {'var_name':
1514a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                                                    handle['name']})
1515a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    for parameter in parameters:
1516a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      out_file.write(self._HASH_UPDATE % {'var_name':
1517a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                                          '%s_bytes' % parameter['name']})
1518a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      out_file.write(self._APPEND_COMMAND_PARAMETER % {'var_name':
1519a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                                                       parameter['name']})
1520a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    # Do authorization based on the hash.
1521a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    out_file.write(self._AUTHORIZE_COMMAND)
1522a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    # Now that the tag and size are finalized, serialize those.
1523a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    out_file.write(self._SERIALIZE_LOCAL_VAR %
1524a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                   {'var_name': 'tag',
1525a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                    'var_type': 'TPMI_ST_COMMAND_TAG'})
1526a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    out_file.write(self._SERIALIZE_LOCAL_VAR % {'var_name': 'command_size',
1527a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                                                'var_type': 'UINT32'})
15286a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    out_file.write(self._SERIALIZE_FUNCTION_END)
1529a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn
15306a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  def OutputParseFunction(self, out_file):
15316a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    """Generates a parse function for the command outputs.
1532a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn
1533a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    Args:
1534a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      out_file: Generated code is written to this file.
1535a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    """
15361aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn    out_file.write(self._RESPONSE_PARSER_START % {
15371aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn        'method_name': self._MethodName(),
15381aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn        'method_args': self._ParseArgs()})
1539a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    # Parse the header -- this should always exist.
1540a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    out_file.write(self._PARSE_LOCAL_VAR % {'var_name': 'tag',
1541a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                                            'var_type': 'TPM_ST'})
1542a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    out_file.write(self._PARSE_LOCAL_VAR % {'var_name': 'response_size',
1543a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                                            'var_type': 'UINT32'})
1544a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    out_file.write(self._PARSE_LOCAL_VAR % {'var_name': 'response_code',
1545a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                                            'var_type': 'TPM_RC'})
1546a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    # Handle the error case.
1547a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    out_file.write(self._RESPONSE_ERROR_CHECK)
1548ba2b57d4c899bb28f037a38e18b1bc0361a332aaDarren Krahn    # Categorize arguments as either handles or parameters.
1549ba2b57d4c899bb28f037a38e18b1bc0361a332aaDarren Krahn    handles, parameters = self._SplitArgs(self.response_args)
1550ba2b57d4c899bb28f037a38e18b1bc0361a332aaDarren Krahn    # Parse any handles.
1551ba2b57d4c899bb28f037a38e18b1bc0361a332aaDarren Krahn    for handle in handles:
1552ba2b57d4c899bb28f037a38e18b1bc0361a332aaDarren Krahn      out_file.write(self._PARSE_ARG_VAR % {'var_name': handle['name'],
1553ba2b57d4c899bb28f037a38e18b1bc0361a332aaDarren Krahn                                            'var_type': handle['type']})
1554a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    # Setup a serialized command code which is needed for the response hash.
1555a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    out_file.write(self._DECLARE_COMMAND_CODE % {'command_code':
1556a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                                                 self.command_code})
1557a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    out_file.write(self._SERIALIZE_LOCAL_VAR % {'var_name': 'command_code',
1558a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                                                'var_type': 'TPM_CC'})
1559a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    # Split out the authorization section.
1560a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    out_file.write(self._RESPONSE_SECTION_SPLIT)
1561a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    # Compute the response hash.
1562a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    out_file.write(self._HASH_START)
1563a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    out_file.write(self._HASH_UPDATE % {'var_name': 'response_code_bytes'})
1564a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    out_file.write(self._HASH_UPDATE % {'var_name': 'command_code_bytes'})
1565a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    out_file.write(self._HASH_UPDATE % {'var_name': 'buffer'})
1566a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    # Do authorization related stuff.
1567a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    out_file.write(self._AUTHORIZE_RESPONSE)
1568a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    # Parse response parameters.
1569ba2b57d4c899bb28f037a38e18b1bc0361a332aaDarren Krahn    for arg in parameters:
15706a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      out_file.write(self._PARSE_ARG_VAR % {'var_name': arg['name'],
15716a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn                                            'var_type': arg['type']})
1572ba2b57d4c899bb28f037a38e18b1bc0361a332aaDarren Krahn    if parameters and IsTPM2B(parameters[0]['type']):
1573a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      out_file.write(self._DECRYPT_PARAMETER % {'var_name':
1574ba2b57d4c899bb28f037a38e18b1bc0361a332aaDarren Krahn                                                parameters[0]['name'],
1575a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                                                'var_type':
1576ba2b57d4c899bb28f037a38e18b1bc0361a332aaDarren Krahn                                                parameters[0]['type']})
1577a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    out_file.write(self._RESPONSE_PARSER_END)
1578a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn
15796a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  def OutputMethodImplementation(self, out_file):
15806a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    """Generates the implementation of a Tpm class method for this command.
15816a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn
15826a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    The method assembles a command to be sent unmodified to the TPM and invokes
15836a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    the CommandTransceiver with the command. Errors are reported directly to the
15846a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    response callback via the error callback (see OutputErrorCallback).
15856a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn
15866a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    Args:
15876a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      out_file: Generated code is written to this file.
15886a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    """
15891aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn    out_file.write(self._ASYNC_METHOD % {
15901aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn        'method_name': self._MethodName(),
15911aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn        'method_args': self._AsyncArgs(),
15921aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn        'method_arg_names': self._ArgNameList(self._RequestArgs(),
15931aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn                                              trailing_comma=True)})
15941aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn    out_file.write(self._SYNC_METHOD % {
15951aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn        'method_name': self._MethodName(),
15961aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn        'method_args': self._SyncArgs(),
15971aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn        'method_arg_names_in': self._ArgNameList(self._RequestArgs(),
15981aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn                                                 trailing_comma=True),
15991aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn        'method_arg_names_out': self._ArgNameList(self.response_args,
16001aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn                                                  trailing_comma=True)})
16016a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn
16026a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  def OutputErrorCallback(self, out_file):
16036a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    """Generates the implementation of an error callback for this command.
16046a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn
16056a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    The error callback simply calls the command response callback with the error
16066a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    as the first argument and default values for all other arguments.
16076a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn
16086a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    Args:
16096a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      out_file: Generated code is written to this file.
16106a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    """
16116a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    out_file.write(self._ERROR_CALLBACK_START % {'method_name':
16126a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn                                                 self._MethodName()})
16136a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    for arg in self.response_args:
16146a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      out_file.write(self._ERROR_CALLBACK_ARG % {'arg_type': arg['type']})
16156a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    out_file.write(self._ERROR_CALLBACK_END)
16166a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn
16176a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  def OutputResponseCallback(self, out_file):
16186a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    """Generates the implementation of a response callback for this command.
16196a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn
16206a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    The response callback takes the unmodified response from the TPM, parses it,
16216a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    and invokes the original response callback with the parsed response args.
16226a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    Errors during parsing or from the TPM are reported directly to the response
16236a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    callback via the error callback (see OutputErrorCallback).
16246a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn
16256a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    Args:
16266a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      out_file: Generated code is written to this file.
16276a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    """
16286a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    out_file.write(self._RESPONSE_CALLBACK_START % {'method_name':
16296a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn                                                    self._MethodName()})
16306a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    for arg in self.response_args:
16316a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      out_file.write(self._DECLARE_ARG_VAR % {'var_type': arg['type'],
16326a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn                                              'var_name': arg['name']})
16331aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn    out_file.write(self._RESPONSE_CALLBACK_END % {
16341aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn        'method_name': self._MethodName(),
16351aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn        'method_arg_names_in': self._ArgNameList(self.response_args,
16361aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn                                                 leading_comma=True),
16371aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn        'method_arg_names_out': self._ArgNameList(self.response_args,
16381aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn                                                  prefix='&',
16391aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn                                                  trailing_comma=True)})
16406a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn
1641bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn  def GetNumberOfRequestHandles(self):
1642bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn    """Returns the number of input handles for this command."""
1643bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn    return len(self._SplitArgs(self.request_args)[0])
1644bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn
1645bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn  def GetNumberOfResponseHandles(self):
1646bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn    """Returns the number of output handles for this command."""
1647bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn    return len(self._SplitArgs(self.response_args)[0])
1648bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn
16496a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  def _OutputMethodSignatures(self, out_file):
165089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Prints method declaration statements for this command.
165189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
165289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    This includes a method to serialize a request, a method to parse a response,
165389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    and methods for synchronous and asynchronous calls.
165489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
165589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Args:
165689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      out_file: The output file.
165789ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
16581aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn    out_file.write('  static TPM_RC SerializeCommand_%s(%s);\n' % (
16591aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn        self._MethodName(), self._SerializeArgs()))
16601aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn    out_file.write('  static TPM_RC ParseResponse_%s(%s);\n' % (
16611aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn        self._MethodName(), self._ParseArgs()))
1662a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    out_file.write('  virtual void %s(%s);\n' % (self._MethodName(),
16636a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn                                                 self._AsyncArgs()))
16646a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    out_file.write('  virtual TPM_RC %sSync(%s);\n' % (self._MethodName(),
16656a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn                                                       self._SyncArgs()))
166664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
166764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def _OutputCallbackSignature(self, out_file):
166889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Prints a callback typedef for this command.
166989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
167089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Args:
167189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      out_file: The output file.
167289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
16736a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    args = self._InputArgList(self.response_args)
167464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    if args:
167564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      args = ',' + args
167664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    args = '\n      TPM_RC response_code' + args
167764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    out_file.write('  typedef base::Callback<void(%s)> %sResponse;\n' %
167864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn                   (args, self._MethodName()))
167964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
168064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def _MethodName(self):
168189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Creates an appropriate generated method name for the command.
168289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
168389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    We use the command name without the TPM2_ prefix.
168489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
168589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Returns:
168689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      The method name.
168789ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
168864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    if not self.name.startswith('TPM2_'):
168964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      return self.name
169064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    return self.name[5:]
169164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
16926a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  def _InputArgList(self, args):
169389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Formats a list of input arguments for use in a function declaration.
169489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
169589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Args:
169689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      args: An argument list in the same form as the request_args and
169789ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn          response_args attributes.
169889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
169989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Returns:
170089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      A string which can be used in a function declaration.
170189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
17026a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    if args:
170389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      arg_list = ['const %(type)s& %(name)s' % a for a in args]
17046a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      return '\n      ' + ',\n      '.join(arg_list)
17056a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    return ''
17066a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn
17076a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  def _OutputArgList(self, args):
170889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Formats a list of output arguments for use in a function declaration.
170989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
171089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Args:
171189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      args: An argument list in the same form as the request_args and
171289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn          response_args attributes.
171389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
171489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Returns:
171589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      A string which can be used in a function declaration.
171689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
171764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    if args:
171889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      arg_list = ['%(type)s* %(name)s' % a for a in args]
171964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      return '\n      ' + ',\n      '.join(arg_list)
172064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    return ''
172164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
17226a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  def _ArgNameList(self, args, prefix='', leading_comma=False,
17236a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn                   trailing_comma=False):
172489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Formats a list of arguments for use in a function call statement.
172589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
172689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Args:
172789ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      args: An argument list in the same form as the request_args and
172889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn          response_args attributes.
172989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      prefix: A prefix to be prepended to each argument.
173089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      leading_comma: Whether to include a comma before the first argument.
173189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      trailing_comma: Whether to include a comma after the last argument.
173289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
173389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Returns:
173489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      A string which can be used in a function call statement.
173589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
17366a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    if args:
17376a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      arg_list = [(prefix + a['name']) for a in args]
17386a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      header = ''
17396a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      if leading_comma:
17406a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn        header = ','
17416a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      trailer = ''
17426a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      if trailing_comma:
17436a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn        trailer = ','
17446a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      return header + '\n      ' + ',\n      '.join(arg_list) + trailer
17456a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    return ''
17466a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn
1747a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  def _SplitArgs(self, args):
1748a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    """Splits a list of args into handles and parameters."""
1749a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    handles = []
1750a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    parameters = []
17515f8ca6f3d1405102961386e2747400d183527507Utkarsh Sanghi    # These commands have handles that are serialized into the parameter
17525f8ca6f3d1405102961386e2747400d183527507Utkarsh Sanghi    # section.
17535f8ca6f3d1405102961386e2747400d183527507Utkarsh Sanghi    command_handle_parameters = {
17545f8ca6f3d1405102961386e2747400d183527507Utkarsh Sanghi        'TPM_CC_FlushContext': 'TPMI_DH_CONTEXT',
17555f8ca6f3d1405102961386e2747400d183527507Utkarsh Sanghi        'TPM_CC_Hash': 'TPMI_RH_HIERARCHY',
17565f8ca6f3d1405102961386e2747400d183527507Utkarsh Sanghi        'TPM_CC_LoadExternal': 'TPMI_RH_HIERARCHY',
17575f8ca6f3d1405102961386e2747400d183527507Utkarsh Sanghi        'TPM_CC_SequenceComplete': 'TPMI_RH_HIERARCHY',
17585f8ca6f3d1405102961386e2747400d183527507Utkarsh Sanghi    }
17595f8ca6f3d1405102961386e2747400d183527507Utkarsh Sanghi    # Handle type that appears in the handle section.
176003d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn    always_handle = set(['TPM_HANDLE'])
17615f8ca6f3d1405102961386e2747400d183527507Utkarsh Sanghi    # Handle types that always appear as command parameters.
176252e2a45f585fbe34032eae5b094a092afdf217caDarren Krahn    always_parameter = set(['TPMI_RH_ENABLES', 'TPMI_DH_PERSISTENT'])
17635f8ca6f3d1405102961386e2747400d183527507Utkarsh Sanghi    if self.command_code in command_handle_parameters:
17645f8ca6f3d1405102961386e2747400d183527507Utkarsh Sanghi      always_parameter.add(command_handle_parameters[self.command_code])
1765a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    for arg in args:
176603d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn      if (arg['type'] in always_handle or
176703d54dfbcbdd04384e8c0419b7c45282664a2c1aDarren Krahn          (self._HANDLE_RE.search(arg['type']) and
176852e2a45f585fbe34032eae5b094a092afdf217caDarren Krahn           arg['type'] not in always_parameter)):
1769a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn        handles.append(arg)
1770a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      else:
1771a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn        parameters.append(arg)
1772a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    return handles, parameters
1773a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn
17746a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  def _RequestArgs(self):
177589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Computes the argument list for a Tpm request.
177689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
177789ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    For every handle argument a handle name argument is added.
177889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
1779a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    handles, parameters = self._SplitArgs(self.request_args)
1780a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    args = []
1781a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    # Add a name argument for every handle.  We'll need it to compute cpHash.
1782a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    for handle in handles:
1783a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      args.append(handle)
17846a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      args.append({'type': 'std::string',
1785a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                   'name': '%s_name' % handle['name']})
1786a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    for parameter in parameters:
1787a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn      args.append(parameter)
17886a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    return args
17896a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn
17906a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  def _AsyncArgs(self):
179189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Returns a formatted argument list for an asynchronous method."""
17926a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    args = self._InputArgList(self._RequestArgs())
17936a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    if args:
17946a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      args += ','
17956a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    return (args + self._DELEGATE_ARG + ',' +
17966a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn            self._CALLBACK_ARG % {'method_name': self._MethodName()})
17976a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn
17986a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  def _SyncArgs(self):
179989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Returns a formatted argument list for a synchronous method."""
18006a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    request_arg_list = self._InputArgList(self._RequestArgs())
18016a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    if request_arg_list:
18026a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      request_arg_list += ','
18036a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    response_arg_list = self._OutputArgList(self.response_args)
18046a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    if response_arg_list:
18056a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      response_arg_list += ','
18066a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    return request_arg_list + response_arg_list + self._DELEGATE_ARG
18076a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn
18086a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  def _SerializeArgs(self):
180989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Returns a formatted argument list for a request-serialize method."""
18106a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    args = self._InputArgList(self._RequestArgs())
18116a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    if args:
18126a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      args += ','
18136a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    return args + self._SERIALIZE_ARG + ',' + self._DELEGATE_ARG
18146a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn
18156a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn  def _ParseArgs(self):
181689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Returns a formatted argument list for a response-parse method."""
18176a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    args = self._OutputArgList(self.response_args)
18186a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    if args:
18196a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      args = ',' + args
18206a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    return self._PARSE_ARG + args + ',' + self._DELEGATE_ARG
1821a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn
182264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
182364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahnclass CommandParser(object):
182464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  """Command definition parser.
182564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
182664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  The input text file is extracted from the PDF file containing the TPM
182764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  command specification from the Trusted Computing Group. The syntax
182864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  of the text file is defined by extract_commands.sh.
182964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  """
183064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
183164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  # Regular expressions to pull relevant bits from annotated lines.
183264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _INPUT_START_RE = re.compile(r'^_INPUT_START\s+(\w+)$')
183364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _OUTPUT_START_RE = re.compile(r'^_OUTPUT_START\s+(\w+)$')
183464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _TYPE_RE = re.compile(r'^_TYPE\s+(\w+)$')
183564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _NAME_RE = re.compile(r'^_NAME\s+(\w+)$')
183664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  # Pull the command code from a comment like: _COMMENT TPM_CC_Startup {NV}.
183764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _COMMENT_CC_RE = re.compile(r'^_COMMENT\s+(TPM_CC_\w+).*$')
183864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _COMMENT_RE = re.compile(r'^_COMMENT\s+(.*)')
183964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  # Args which are handled internally by the generated method.
184064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  _INTERNAL_ARGS = ('tag', 'Tag', 'commandSize', 'commandCode', 'responseSize',
1841cdbfb49f8b6344f843075acf4926b97bdf5418a1ChromeOS Developer                    'responseCode', 'returnCode')
184264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
184364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def __init__(self, in_file):
184489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Initializes a CommandParser instance.
184589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
184689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Args:
184789ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      in_file: A file as returned by open() which has been opened for reading.
184889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
184964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self._line = None
185064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self._in_file = in_file
185164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
185264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def _NextLine(self):
185389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Gets the next input line.
185489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
185589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Returns:
185689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      The next input line if another line is available, None otherwise.
185789ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
185864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    try:
185964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      self._line = self._in_file.next()
186064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    except StopIteration:
186164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      self._line = None
186264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
186364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def Parse(self):
186464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    """Parses everything in a commands file.
186564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
186664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    Returns:
186764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      A list of extracted Command objects.
186864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    """
186964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    commands = []
187064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self._NextLine()
187164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    if self._line != '_BEGIN\n':
187289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      print('Invalid format for first line: %s\n' % self._line)
187364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      return commands
187464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self._NextLine()
187564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
187664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    while self._line != '_END\n':
187764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      cmd = self._ParseCommand()
187864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      if not cmd:
187964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        break
188064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      commands.append(cmd)
188164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    return commands
188264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
188364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def _ParseCommand(self):
188489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Parses inputs and outputs for a single TPM command.
188589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
188689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Returns:
188789ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      A single Command object.
188889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
188964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    match = self._INPUT_START_RE.search(self._line)
189064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    if not match:
189189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      print('Cannot match command input from line: %s\n' % self._line)
189264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      return None
189364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    name = match.group(1)
189464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    cmd = Command(name)
189564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self._NextLine()
189664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    cmd.request_args = self._ParseCommandArgs(cmd)
189764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    match = self._OUTPUT_START_RE.search(self._line)
189864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    if not match or match.group(1) != name:
189989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      print('Cannot match command output from line: %s\n' % self._line)
190064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      return None
190164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    self._NextLine()
190264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    cmd.response_args = self._ParseCommandArgs(cmd)
19036a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    request_var_names = set([arg['name'] for arg in cmd.request_args])
19046a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    for arg in cmd.response_args:
19056a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn      if arg['name'] in request_var_names:
19066a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn        arg['name'] += '_out'
190764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    if not cmd.command_code:
190889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      print('Command code not found for %s' % name)
190964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      return None
191064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    return cmd
191164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
191264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  def _ParseCommandArgs(self, cmd):
191389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """Parses a set of arguments for a command.
191489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
191589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    The arguments may be input or output arguments.
191689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
191789ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Args:
191889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      cmd: The current Command object. The command_code attribute will be set if
191989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn          such a constant is parsed.
192089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
192189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    Returns:
192289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      A list of arguments in the same form as the Command.request_args and
192389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn      Command.response_args attributes.
192489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    """
192564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    args = []
192664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    match = self._TYPE_RE.search(self._line)
192764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    while match:
192864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      arg_type = match.group(1)
192964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      self._NextLine()
193064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      match = self._NAME_RE.search(self._line)
193164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      if not match:
193289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn        print('Cannot match argument name from line: %s\n' % self._line)
193364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        break
193464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      arg_name = match.group(1)
193564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      self._NextLine()
193664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      match = self._COMMENT_CC_RE.search(self._line)
193764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      if match:
193864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        cmd.command_code = match.group(1)
193964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      match = self._COMMENT_RE.search(self._line)
194064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      if match:
194164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        self._NextLine()
194264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      if arg_name not in self._INTERNAL_ARGS:
194364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn        args.append({'type': arg_type,
1944a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn                     'name': FixName(arg_name)})
194564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn      match = self._TYPE_RE.search(self._line)
194664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    return args
194764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
194864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
1949bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahndef GenerateHandleCountFunctions(commands, out_file):
1950bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn  """Generates the GetNumberOf*Handles functions given a list of commands.
1951bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn
1952bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn  Args:
1953bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn    commands: A list of Command objects.
1954bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn    out_file: The output file.
1955bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn  """
1956bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn  out_file.write(_HANDLE_COUNT_FUNCTION_START % {'handle_type': 'Request'})
1957bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn  for command in commands:
1958bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn    out_file.write(_HANDLE_COUNT_FUNCTION_CASE %
1959bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn                   {'command_code': command.command_code,
1960bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn                    'handle_count': command.GetNumberOfRequestHandles()})
1961bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn  out_file.write(_HANDLE_COUNT_FUNCTION_END)
1962bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn  out_file.write(_HANDLE_COUNT_FUNCTION_START % {'handle_type': 'Response'})
1963bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn  for command in commands:
1964bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn    out_file.write(_HANDLE_COUNT_FUNCTION_CASE %
1965bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn                   {'command_code': command.command_code,
1966bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn                    'handle_count': command.GetNumberOfResponseHandles()})
1967bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn  out_file.write(_HANDLE_COUNT_FUNCTION_END)
1968bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn
1969bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn
197064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahndef GenerateHeader(types, constants, structs, defines, typemap, commands):
197164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  """Generates a header file with declarations for all given generator objects.
197264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
197364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  Args:
197464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    types: A list of Typedef objects.
197564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    constants: A list of Constant objects.
197664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    structs: A list of Structure objects.
197764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    defines: A list of Define objects.
197864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    typemap: A dict mapping type names to the corresponding object.
197964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    commands: A list of Command objects.
198064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  """
198164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  out_file = open(_OUTPUT_FILE_H, 'w')
198264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  out_file.write(_COPYRIGHT_HEADER)
198364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  guard_name = 'TRUNKS_%s_' % _OUTPUT_FILE_H.upper().replace('.', '_')
198464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  out_file.write(_HEADER_FILE_GUARD_HEADER % {'name': guard_name})
198564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  out_file.write(_HEADER_FILE_INCLUDES)
198664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  out_file.write(_NAMESPACE_BEGIN)
19872c1ce244d871c38f48e6bef8af854fa4e7f30c08Darren Krahn  out_file.write(_FORWARD_DECLARATIONS)
1988b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  out_file.write('\n')
198964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  # These types are built-in or defined by <stdint.h>; they serve as base cases
199064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  # when defining type dependencies.
1991e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn  defined_types = set(_BASIC_TYPES)
199264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  # Generate defines.  These must be generated before any other code.
199364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  for define in defines:
199464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    define.Output(out_file)
199564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  out_file.write('\n')
199664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  # Generate typedefs.  These are declared before structs because they are not
199764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  # likely to depend on structs and when they do a simple forward declaration
199864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  # for the struct can be generated.  This improves the readability of the
199964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  # generated code.
200064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  for typedef in types:
200164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    typedef.Output(out_file, defined_types, typemap)
200264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  out_file.write('\n')
200364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  # Generate constant definitions.  Again, generated before structs to improve
200464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  # readability.
200564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  for constant in constants:
200664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    constant.Output(out_file, defined_types, typemap)
200764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  out_file.write('\n')
200864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  # Generate structs.  All non-struct dependencies should be already declared.
200964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  for struct in structs:
201064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    struct.Output(out_file, defined_types, typemap)
2011bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn  # Helper function declarations.
2012bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn  out_file.write(_FUNCTION_DECLARATIONS)
2013e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn  # Generate serialize / parse function declarations.
2014e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn  for basic_type in _BASIC_TYPES:
2015e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn    out_file.write(_SERIALIZE_DECLARATION % {'type': basic_type})
2016e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn  for typedef in types:
2017e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn    out_file.write(_SERIALIZE_DECLARATION % {'type': typedef.new_type})
2018e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn  for struct in structs:
2019e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn    out_file.write(_SERIALIZE_DECLARATION % {'type': struct.name})
2020434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn    if struct.IsSimpleTPM2B():
2021434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn      out_file.write(_SIMPLE_TPM2B_HELPERS_DECLARATION % {'type': struct.name})
2022434cfb322d09c125018fc0864f42d36dff3014e6Darren Krahn    elif struct.IsComplexTPM2B():
20231aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn      out_file.write(_COMPLEX_TPM2B_HELPERS_DECLARATION % {
20241aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn          'type': struct.name,
20251aeb5969d4f286e36fe88152ad8c96cff668c25fDarren Krahn          'inner_type': struct.fields[1][0]})
202664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  # Generate a declaration for a 'Tpm' class, which includes one method for
202764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  # every TPM 2.0 command.
202864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  out_file.write(_CLASS_BEGIN)
202964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  for command in commands:
203064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    command.OutputDeclarations(out_file)
203164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  out_file.write(_CLASS_END)
203264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  out_file.write(_NAMESPACE_END)
203364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  out_file.write(_HEADER_FILE_GUARD_FOOTER % {'name': guard_name})
203464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  out_file.close()
203564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
203664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
203764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahndef GenerateImplementation(types, structs, typemap, commands):
203864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  """Generates implementation code for each command.
203964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
204064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  Args:
204164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    types: A list of Typedef objects.
204264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    structs: A list of Structure objects.
204364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    typemap: A dict mapping type names to the corresponding object.
204464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn    commands: A list of Command objects.
204564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  """
204664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  out_file = open(_OUTPUT_FILE_CC, 'w')
204764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  out_file.write(_COPYRIGHT_HEADER)
204864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  out_file.write(_LOCAL_INCLUDE % {'filename': _OUTPUT_FILE_H})
2049b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  out_file.write(_IMPLEMENTATION_FILE_INCLUDES)
205064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  out_file.write(_NAMESPACE_BEGIN)
2051bb9ae5a756c41d1a420bae3ddf55df6a86f4af76Darren Krahn  GenerateHandleCountFunctions(commands, out_file)
2052e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn  serialized_types = set(_BASIC_TYPES)
2053e1c5e72731573f043c12a9d0abc40dda839abc4eDarren Krahn  for basic_type in _BASIC_TYPES:
2054b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    out_file.write(_SERIALIZE_BASIC_TYPE % {'type': basic_type})
2055b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  for typedef in types:
2056b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    typedef.OutputSerialize(out_file, serialized_types, typemap)
2057b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn  for struct in structs:
2058b49375c15718568c70ebfd55eaee790a2b693944Darren Krahn    struct.OutputSerialize(out_file, serialized_types, typemap)
2059a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn  for command in commands:
20606a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    command.OutputSerializeFunction(out_file)
20616a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    command.OutputParseFunction(out_file)
2062a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    command.OutputErrorCallback(out_file)
20636a5f9fd320f2bd202653d09bad15a75474d49360Darren Krahn    command.OutputResponseCallback(out_file)
2064a0471fe9c5a68344516f5897a1f1c342438e514eDarren Krahn    command.OutputMethodImplementation(out_file)
206564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  out_file.write(_NAMESPACE_END)
206664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  out_file.close()
206764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
206864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
206964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahndef main():
207089ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  """A main function.
207189ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
207289ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  Both a TPM structures file and commands file are parsed and C++ header and C++
207389ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  implementation file are generated.
207489ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn
207589ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  Positional Args:
207689ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    structures_file: The extracted TPM structures file.
207789ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn    commands_file: The extracted TPM commands file.
207889ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  """
207964cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  parser = argparse.ArgumentParser(description='TPM 2.0 code generator')
208064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  parser.add_argument('structures_file')
208164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  parser.add_argument('commands_file')
208264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  args = parser.parse_args()
208364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  structure_parser = StructureParser(open(args.structures_file))
208464cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  types, constants, structs, defines, typemap = structure_parser.Parse()
208564cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  command_parser = CommandParser(open(args.commands_file))
208664cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  commands = command_parser.Parse()
208764cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  GenerateHeader(types, constants, structs, defines, typemap, commands)
208864cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  GenerateImplementation(types, structs, typemap, commands)
208989ddcfe1d4e8d9907be18a3038c6f2ce6a3cd993Darren Krahn  print('Processed %d commands.' % len(commands))
209064cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
209164cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn
209264cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahnif __name__ == '__main__':
209364cad7ce8e7c1e7ee10e25a162af219b0e06741cDarren Krahn  main()
2094