blob: 5c736e8a1f11c04508de474b06e647a1fa81bdf6 [file] [log] [blame]
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001#!/usr/bin/python2
2
3# Copyright 2015 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7"""A code generator for TPM 2.0 structures.
8
9The structure generator takes as input a structures file as emitted by the
10extract_structures.sh script. It outputs valid C into tpm_generated.{h,c}.
11tpm_generated.{h,c} consist of functions to marshal TPM2.0 structures.
12
13The input grammar is documented in extract_structures.sh. Sample input for
14structures looks like this:
15_BEGIN_TYPES
16_OLD_TYPE UINT32
17_NEW_TYPE TPM_HANDLE
18_END
19_BEGIN_CONSTANTS
20_CONSTANTS (UINT32) TPM_SPEC
21_TYPE UINT32
22_NAME TPM_SPEC_FAMILY
23_VALUE 0x322E3000
24_NAME TPM_SPEC_LEVEL
25_VALUE 00
26_END
27_BEGIN_STRUCTURES
28_STRUCTURE TPMS_TIME_INFO
29_TYPE UINT64
30_NAME time
31_TYPE TPMS_CLOCK_INFO
32_NAME clockInfo
33_END
34"""
35
36from __future__ import print_function
37
ChromeOS Developer9edfbac2015-07-17 16:33:16 -070038import re
39import collections
40from subprocess import call
41
42import union_selectors
43
44_BASIC_TYPES = ['uint8_t', 'int8_t', 'uint16_t', 'int16_t', 'uint32_t',
45 'int32_t', 'uint64_t', 'int64_t']
46_OUTPUT_FILE_H = 'tpm_generated.h'
47_OUTPUT_FILE_CC = 'tpm_generated.c'
48_COPYRIGHT_HEADER = (
49 '// Copyright 2015 The Chromium OS Authors. All rights reserved.\n'
50 '// Use of this source code is governed by a BSD-style license that can '
51 'be\n'
52 '// found in the LICENSE file.\n'
53 '\n'
54 '// THIS CODE IS GENERATED - DO NOT MODIFY!\n')
55_HEADER_FILE_GUARD_HEADER = """
56#ifndef %(name)s
57#define %(name)s
58"""
59_HEADER_FILE_GUARD_FOOTER = """
60#endif // %(name)s
61"""
62_HEADER_FILE_INCLUDES = """
63#include <endian.h>
64#include <string.h>
65
66#include "TPM_Types.h"
67#include "Tpm.h"
68"""
69_IMPLEMENTATION_FILE_INCLUDES = """
70#include "tpm_generated.h"
71"""
72# Function signatures for generated marshaling code are specified in TCG TPM2.0
73# Library Specification, Part 4: Supporting Routines, sections 4.2.2 and 4.2.3.
74_MARSHAL_BASIC_TYPE = """
75UINT16 %(type)s_Marshal(%(type)s *source, BYTE **buffer, INT32 *size) {
Jocelyn Bohrfb668122015-07-30 10:17:56 -070076 %(type)s value_net = *source;
ChromeOS Developer9edfbac2015-07-17 16:33:16 -070077 if (!size || *size < sizeof(%(type)s)) {
78 return sizeof(%(type)s);
79 }
ChromeOS Developer9edfbac2015-07-17 16:33:16 -070080 switch (sizeof(%(type)s)) {
81 case 2:
82 value_net = htobe16(*source);
83 break;
84 case 4:
85 value_net = htobe32(*source);
86 break;
87 case 8:
88 value_net = htobe64(*source);
89 break;
90 default:
91 break;
92 }
93 memcpy(*buffer, &value_net, sizeof(%(type)s));
94 *buffer += sizeof(%(type)s);
95 *size -= sizeof(%(type)s);
96 return sizeof(%(type)s);
97}
98
99TPM_RC %(type)s_Unmarshal(%(type)s *target, BYTE **buffer, INT32 *size) {
Jocelyn Bohrfb668122015-07-30 10:17:56 -0700100 %(type)s value_net = 0;
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700101 if (!size || *size < sizeof(%(type)s)) {
102 return TPM_RC_INSUFFICIENT;
103 }
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700104 memcpy(&value_net, *buffer, sizeof(%(type)s));
105 switch (sizeof(%(type)s)) {
106 case 2:
107 *target = be16toh(value_net);
108 break;
109 case 4:
110 *target = be32toh(value_net);
111 break;
112 case 8:
113 *target = be64toh(value_net);
114 break;
115 default:
116 *target = value_net;
117 }
118 *buffer += sizeof(%(type)s);
119 *size -= sizeof(%(type)s);
120 return TPM_RC_SUCCESS;
121}
122"""
123_STANDARD_MARSHAL_DECLARATION = """
124UINT16 %(type)s_Marshal(
125 %(type)s *source,
126 BYTE **buffer,
127 INT32 *size);
128
129TPM_RC %(type)s_Unmarshal(
130 %(type)s *target,
131 BYTE **buffer,
132 INT32 *size);
133"""
134
135def IsTPM2B(name):
136 return name.startswith('TPM2B_')
137
138
139class TPMType(object):
140 """Base type for all TPMTypes
141
142 Contains functions and string literals common to all TPM types.
143 """
144 # A function to marshal a TPM typedef.
145 _TYPEDEF_MARSHAL_FUNCTION = """
146UINT16 %(new_type)s_Marshal(
147 %(new_type)s *source,
148 BYTE **buffer,
149 INT32 *size) {
150 return %(old_type)s_Marshal(source, buffer, size);
151}
152"""
153 # The function signature and unmarshaling call to the base type of a TPM
154 # typedef. After the value is unmarshaled, additional validation code is
155 # generated based on tables in TCG TPM2.0 Library Specification, Part 2:
156 # Structures.
157 _TYPEDEF_UNMARSHAL_START = """
158TPM_RC %(new_type)s_Unmarshal(
159 %(new_type)s *target,
160 BYTE **buffer,
161 INT32 *size) {
162 TPM_RC result;
163 result = %(old_type)s_Unmarshal(target, buffer, size);
164 if (result != TPM_RC_SUCCESS) {
165 return result;
166 }"""
167 _UNMARSHAL_END = '\n return TPM_RC_SUCCESS;\n}\n'
168 # Snippets of code for value validation.
169 _VALUE_START_SWITCH = '\n switch (%(name)s) {'
170 _VALUE_CASE = '\n case %(value)s:'
171 _VALUE_CASE_IFDEF = '\n#ifdef %(value)s\n case %(value)s:\n#endif'
172 _VALUE_END_SWITCH = """
173 break;
174 default:
175 return %(error_code)s;
176 }"""
177 # A declaration for marshaling and unmarshaling functions for a TPM type.
178 _MARSHAL_DECLARATION = _STANDARD_MARSHAL_DECLARATION
179 # Snippets of code which make calls to marshaling functions. Marshals a value
180 # of type 'type' into a field 'name' within a structure. This is used in
181 # generation of structure and command marshaling code.
182 _MARSHAL_CALL = """
183 total_size += %(type)s_Marshal(
184 &source->%(name)s, buffer, size);"""
185 _UNMARSHAL_CALL = """
186 result = %(type)s_Unmarshal(
187 &target->%(name)s, buffer, size);
188 if (result != TPM_RC_SUCCESS) {
189 return result;
190 }"""
191
192 def HasConditional(self):
193 """Returns true if TPMType has a conditional value."""
194 return False
195
Vadim Bendeburyb85286c2015-09-15 14:25:48 -0700196 def OutputMarshalCall(self, out_file, field_type, field_name, _):
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700197 """Write a call to Marshal function for TPMType to |out_file|.
198
199 Accumulates a variable 'total_size' with the result of marshaling
200 field |field_name| in structure 'source'.
201
202 Args:
203 out_file: The output file.
204 field_type: The type of the field in 'source' struct to be marshalled.
205 field_name: The name of the field in 'source' struct to be marshalled.
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700206 """
207 out_file.write(self._MARSHAL_CALL % {'type': field_type,
208 'name': field_name})
209
210 def OutputUnmarshalCall(
Vadim Bendeburyb85286c2015-09-15 14:25:48 -0700211 self, out_file, field_type, field_name, _):
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700212 """Write a call to Unmarshal function for TPMType to |out_file|.
213
214 Assigns result of unmarshaling field |field_name| in structure 'source'
215 to variable 'result'. Returns if the unmarshalling was unsuccessful.
216
217 Args:
218 out_file: The output file.
219 field_type: The type of the field in 'target' struct to be unmarshalled.
220 field_name: The name of the field in 'target' struct to be unmarshalled.
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700221 """
222 out_file.write(self._UNMARSHAL_CALL % {'type': field_type,
223 'name': field_name})
224
225 def _OutputTypedefMarshalDecl(self, out_file, declared_types, typemap):
226 """Write marshal declarations for TPM typedefs to |out_file|.
227
228 Can only be called on Typedef, ConstantType, AttributeStruct, and
229 Interface objects.
230
231 Args:
232 out_file: The output file.
233 declared_types: A set of types for which marshal and unmarshal function
234 declarations have already been generated.
235 typemap: A dict mapping type names to the corresponding object.
236 """
237 if self.new_type in declared_types:
238 return
239 if self.old_type not in declared_types:
240 typemap[self.old_type].OutputMarshalDecl(
241 out_file, declared_types, typemap)
242 out_file.write(self._MARSHAL_DECLARATION % {'type': self.new_type})
243 declared_types.add(self.new_type)
244
Vadim Bendeburyb85286c2015-09-15 14:25:48 -0700245 def _OutputStructOrUnionMarshalDecl(self, out_file, declared_types):
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700246 """Write marshal declarations for a TPM Structure or Union.
247
248 Can only be called on Structure and Union objects.
249
250 Args:
251 out_file: The output file.
252 declared_types: A set of types for which marshal and unmarshal function
253 declarations have already been generated.
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700254 """
255 # TPMU_NAME and TPMU_ENCRYPTED_SECRET type are never used across the
256 # interface.
257 if (self.name in declared_types or
258 self.name == 'TPMU_NAME' or
259 self.name == 'TPMU_ENCRYPTED_SECRET'):
260 return
261 out_file.write(self._MARSHAL_DECLARATION % {'type': self.name})
262 declared_types.add(self.name)
263
264class Typedef(TPMType):
265 """Represents a TPM typedef.
266
267 Attributes:
268 old_type: The existing type in a typedef statement.
269 new_type: The new type in a typedef statement.
270 """
271 # A function to unmarshal a TPM typedef with no extra validation.
272 _TYPEDEF_UNMARSHAL_FUNCTION = """
273TPM_RC %(new_type)s_Unmarshal(
274 %(new_type)s *target,
275 BYTE **buffer,
276 INT32 *size) {
277 return %(old_type)s_Unmarshal(target, buffer, size);
278}
279"""
280 def __init__(self, old_type, new_type):
281 """Initializes a Typedef instance.
282
283 Args:
284 old_type: The base type of the attribute structure.
285 new_type: The name of the type.
286 """
287 self.old_type = old_type
288 self.new_type = new_type
289
290 def OutputMarshalImpl(self, out_file, marshalled_types, typemap):
291 """Writes marshal implementations for Typedef to |out_file|.
292
293 Args:
294 out_file: The output file.
295 marshalled_types: A set of types for which marshal and unmarshal functions
296 have already been generated.
297 typemap: A dict mapping type names to the corresponding object.
298 """
299 if self.new_type in marshalled_types:
300 return
301 if self.old_type not in marshalled_types:
302 typemap[self.old_type].OutputMarshalImpl(
303 out_file, marshalled_types, typemap)
304 out_file.write(self._TYPEDEF_MARSHAL_FUNCTION % {'old_type': self.old_type,
305 'new_type': self.new_type})
306 out_file.write(
307 self._TYPEDEF_UNMARSHAL_FUNCTION % {'old_type': self.old_type,
308 'new_type': self.new_type})
309 marshalled_types.add(self.new_type)
310
311 def OutputMarshalDecl(self, out_file, declared_types, typemap):
312 """Writes marshal declarations for Typedef to |out_file|.
313
314 Args:
315 out_file: The output file.
316 declared_types: A set of types for which marshal and unmarshal function
317 declarations have already been generated.
318 typemap: A dict mapping type names to the corresponding object.
319 """
320 self._OutputTypedefMarshalDecl(out_file, declared_types, typemap)
321
322class ConstantType(TPMType):
323 """Represents a TPM Constant type definition.
324
325 Attributes:
326 old_type: The base type of the constant (e.g. 'int').
327 new_type: The name of the type (e.g. 'TPM_RC').
328 valid_values: The list of valid values this type can take (e.g.
329 'TPM_RC_SUCCESS').
330 error_code: Error to be returned when unmarshalling is unsuccessful.
331 """
332 _CHECK_VALUE = """
333 if (*target == %(value)s) {
334 return TPM_RC_SUCCESS;
335 }"""
336 _CHECK_VALUE_IFDEF = """
337#ifdef %(value)s
338 if (*target == %(value)s) {
339 return TPM_RC_SUCCESS;
340 }
341#endif"""
342 _UNMARSHAL_END = """
343 return %(error_code)s;
344}
345"""
346 _IFDEF_TYPE_RE = re.compile(r'^TPM_(ALG|CC).*')
347
348 def __init__(self, old_type, new_type):
349 """Initializes a ConstantType instance.
350
351 Values are added to valid_values attribute during parsing.
352
353 Args:
354 old_type: The base type of the constant type.
355 new_type: The name of the type.
356 """
357 self.old_type = old_type
358 self.new_type = new_type
359 self.valid_values = []
360 self.error_code = 'TPM_RC_VALUE'
361
362 def _NeedsIfdef(self):
363 """Returns True if new_type is a type which needs ifdef enclosing."""
364 return self._IFDEF_TYPE_RE.search(self.new_type)
365
366 def OutputMarshalImpl(self, out_file, marshalled_types, typemap):
367 """Writes marshal implementations for ConstantType to |out_file|.
368
369 Args:
370 out_file: The output file.
371 marshalled_types: A set of types for which marshal and unmarshal functions
372 have already been generated.
373 typemap: A dict mapping type names to the corresponding object.
374 """
375 if self.new_type in marshalled_types:
376 return
377 if self.old_type not in marshalled_types:
378 typemap[self.old_type].OutputMarshalImpl(
379 out_file, marshalled_types, typemap)
380 out_file.write(self._TYPEDEF_MARSHAL_FUNCTION % {'old_type': self.old_type,
381 'new_type': self.new_type})
382 out_file.write(self._TYPEDEF_UNMARSHAL_START % {'old_type': self.old_type,
383 'new_type': self.new_type})
384 for value in self.valid_values:
385 if self._NeedsIfdef():
386 out_file.write(self._CHECK_VALUE_IFDEF % {'value': value})
387 else:
388 out_file.write(self._CHECK_VALUE % {'value': value})
389 out_file.write(self._UNMARSHAL_END % {'error_code': self.error_code})
390 marshalled_types.add(self.new_type)
391
392 def OutputMarshalDecl(self, out_file, declared_types, typemap):
393 """Writes marshal declarations for ConstantType to |out_file|.
394
395 Args:
396 out_file: The output file.
397 declared_types: A set of types for which marshal and unmarshal function
398 declarations have already been generated.
399 typemap: A dict mapping type names to the corresponding object.
400 """
401 self._OutputTypedefMarshalDecl(out_file, declared_types, typemap)
402
403class AttributeStructure(TPMType):
404 """Represents a TPM attribute structure type definition.
405
406 Attributes:
407 old_type: The base type of the constant (e.g. 'int').
408 new_type: The name of the type (e.g. 'TPMA_OBJECT').
409 reserved: The list of bit bounds where bits must be 0 (e.g. ['10_2','3']).
410 """
411 # Attribute structures need an explicit cast to the base type.
412 _ATTRIBUTE_MARSHAL_FUNCTION = """
413UINT16 %(new_type)s_Marshal(
414 %(new_type)s *source,
415 BYTE **buffer,
416 INT32 *size) {
417 return %(old_type)s_Marshal((%(old_type)s*)source, buffer, size);
418}
419"""
420 _ATTRIBUTE_UNMARSHAL_START = """
421TPM_RC %(new_type)s_Unmarshal(
422 %(new_type)s *target,
423 BYTE **buffer,
424 INT32 *size) {
425 TPM_RC result;
426 result = %(old_type)s_Unmarshal((%(old_type)s*)target, buffer, size);
427 if (result != TPM_RC_SUCCESS) {
428 return result;
429 }"""
430 _CHECK_RESERVED = """
431 if (target->reserved%(bits)s != 0) {
432 return TPM_RC_RESERVED_BITS;
433 }"""
434
435 def __init__(self, old_type, new_type):
436 """Initializes an AttributeStructure instance.
437
438 Values may be added to reserved attribute during parsing.
439
440 Args:
441 old_type: The base type of the attribute structure.
442 new_type: The name of the type.
443 """
444 self.old_type = old_type
445 self.new_type = new_type
446 self.reserved = []
447
448 def OutputMarshalImpl(self, out_file, marshalled_types, typemap):
449 """Writes marshal implementations for AttributStructure to |out_file|.
450
451 Args:
452 out_file: The output file.
453 marshalled_types: A set of types for which marshal and unmarshal functions
454 have already been generated.
455 typemap: A dict mapping type names to the corresponding object.
456 """
457 if self.new_type in marshalled_types:
458 return
459 if self.old_type not in marshalled_types:
460 typemap[self.old_type].OutputMarshalImpl(
461 out_file, marshalled_types, typemap)
462 out_file.write(self._ATTRIBUTE_MARSHAL_FUNCTION %
Vadim Bendeburyb85286c2015-09-15 14:25:48 -0700463 {'old_type': self.old_type,
464 'new_type': self.new_type})
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700465 out_file.write(self._ATTRIBUTE_UNMARSHAL_START %
Vadim Bendeburyb85286c2015-09-15 14:25:48 -0700466 {'old_type': self.old_type,
467 'new_type': self.new_type})
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700468 for bits in self.reserved:
469 out_file.write(self._CHECK_RESERVED % {'bits': bits})
470 out_file.write(self._UNMARSHAL_END)
471 marshalled_types.add(self.new_type)
472
473 def OutputMarshalDecl(self, out_file, declared_types, typemap):
474 """Writes marshal declarations for AttributeStructure to |out_file|.
475
476 Args:
477 out_file: The output file.
478 declared_types: A set of types for which marshal and unmarshal function
479 declarations have already been generated.
480 typemap: A dict mapping type names to the corresponding object.
481 """
482 self._OutputTypedefMarshalDecl(out_file, declared_types, typemap)
483
484class Interface(TPMType):
485 """Represents a TPM interface type definition.
486
487 Attributes:
488 old_type: The base type of the interface (e.g. 'TPM_HANDLE').
489 new_type: The name of the type (e.g. 'TPMI_DH_OBJECT').
490 valid_values: List of valid values for new_type. If this is not empty,
491 valid values for new_type is explicitly defined in the spec.
492 bounds: List of pairs representing bounds. If nonempty, target must fall
493 between one of these bounds.
494 conditional_value: Name of conditionally allowed value. If there is no
495 such value, this variable will be None.
496 supported_values: String literal indicating the name of a list of supported
497 values to be substituted at compile time (e.g. 'AES_KEY_SIZES_BITS').
498 If this is not None, valid values for new_type depends on the
499 implementation.
500 error_code: Return code when an unmarshalling error occurs.
501 """
Jocelyn Bohrfb668122015-07-30 10:17:56 -0700502 _INTERFACE_CONDITIONAL_UNMARSHAL_START = """
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700503TPM_RC %(new_type)s_Unmarshal(
504 %(new_type)s *target,
505 BYTE **buffer,
506 INT32 *size,
507 BOOL allow_conditional_value) {
Jocelyn Bohrfb668122015-07-30 10:17:56 -0700508 TPM_RC result;"""
509 _INTERFACE_UNMARSHAL_START = """
510TPM_RC %(new_type)s_Unmarshal(
511 %(new_type)s *target,
512 BYTE **buffer,
513 INT32 *size) {
514 TPM_RC result;"""
515 _UNMARSHAL_VALUE = """
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700516 result = %(old_type)s_Unmarshal(target, buffer, size);
517 if (result != TPM_RC_SUCCESS) {
518 return result;
519 }"""
Jocelyn Bohrfb668122015-07-30 10:17:56 -0700520 _SETUP_CHECK_SUPPORTED_VALUES = """
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700521 uint16_t supported_values[] = %(supported_values)s;
522 size_t length = sizeof(supported_values)/sizeof(supported_values[0]);
523 size_t i;
Jocelyn Bohrfb668122015-07-30 10:17:56 -0700524 BOOL is_supported_value = FALSE;"""
525 _CHECK_SUPPORTED_VALUES = """
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700526 for (i = 0; i < length; ++i) {
527 if (*target == supported_values[i]) {
528 is_supported_value = TRUE;
529 break;
530 }
531 }
532 if (!is_supported_value) {
533 return %(error_code)s;
534 }"""
535 _CHECK_CONDITIONAL = """
536 if (*target == %(name)s) {
537 return allow_conditional_value ? TPM_RC_SUCCESS : %(error_code)s;
538 }"""
Jocelyn Bohrfb668122015-07-30 10:17:56 -0700539 _SETUP_CHECK_VALUES = '\n BOOL has_valid_value = FALSE;'
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700540 _VALUE_END_SWITCH = """
541 has_valid_value = TRUE;
542 break;
543 }"""
544 _CHECK_BOUND = """
545 if((*target >= %(lower)s) && (*target <= %(upper)s)) {
546 has_valid_value = TRUE;
547 }"""
548 _CHECK_VALUES_END = """
549 if (!has_valid_value) {
550 return %(error_code)s;
551 }"""
552 _CONDITIONAL_MARSHAL_DECLARATION = """
553UINT16 %(type)s_Marshal(
554 %(type)s *source,
555 BYTE **buffer,
556 INT32 *size);
557
558TPM_RC %(type)s_Unmarshal(
559 %(type)s *target,
560 BYTE **buffer,
561 INT32 *size,
562 BOOL allow_conditioanl_value);
563"""
564 _CONDITIONAL_UNMARSHAL_CALL = """
565 result = %(type)s_Unmarshal(
566 &target->%(name)s, buffer, size, %(flag)s);
567 if (result != TPM_RC_SUCCESS) {
568 return result;
569 }"""
570 _IFDEF_TYPE_RE = re.compile(r'^TPMI_(ALG|ECC)_.*')
571
572 def __init__(self, old_type, new_type):
573 """Initializes an Interface instance.
574
575 Values may be added/assigned to valid_values, bounds, conditional_value,
576 supported_values, and error_code attributes new values during parsing.
577
578 Args:
579 old_type: The base type of the interface.
580 new_type: The name of the type.
581 """
582 self.old_type = old_type
583 self.new_type = new_type
584 self.valid_values = []
585 self.bounds = []
586 self.conditional_value = None
587 self.supported_values = None
588 self.error_code = 'TPM_RC_VALUE'
589
590 def HasConditional(self):
591 """Returns true if Interface has a valid conditional_value."""
592 return self.conditional_value != None
593
594 def _NeedsIfdef(self):
595 """Returns True if new_type is a type which needs ifdef enclosing."""
596 return self._IFDEF_TYPE_RE.search(self.new_type)
597
598 def OutputMarshalImpl(self, out_file, marshalled_types, typemap):
599 """Writes marshal implementation for Interface to |out_file|.
600
601 Args:
602 out_file: The output file.
603 marshalled_types: A set of types for which marshal and unmarshal functions
604 have already been generated.
605 typemap: A dict mapping type names to the corresponding object.
606 """
607 if self.new_type in marshalled_types:
608 return
609 if self.old_type not in marshalled_types:
610 typemap[self.old_type].OutputMarshalImpl(
611 out_file, marshalled_types, typemap)
612 out_file.write(self._TYPEDEF_MARSHAL_FUNCTION % {'old_type': self.old_type,
613 'new_type': self.new_type})
614 if self.conditional_value:
Jocelyn Bohrfb668122015-07-30 10:17:56 -0700615 out_file.write(self._INTERFACE_CONDITIONAL_UNMARSHAL_START %
Vadim Bendeburyb85286c2015-09-15 14:25:48 -0700616 {'old_type': self.old_type,
617 'new_type': self.new_type})
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700618 else:
619 out_file.write(
Jocelyn Bohrfb668122015-07-30 10:17:56 -0700620 self._INTERFACE_UNMARSHAL_START % {'old_type': self.old_type,
621 'new_type': self.new_type})
622 # Creating necessary local variables.
623 if self.supported_values:
624 out_file.write(self._SETUP_CHECK_SUPPORTED_VALUES %
Vadim Bendeburyb85286c2015-09-15 14:25:48 -0700625 {'supported_values': self.supported_values})
Jocelyn Bohrfb668122015-07-30 10:17:56 -0700626 if len(self.valid_values)+len(self.bounds) > 0:
627 out_file.write(self._SETUP_CHECK_VALUES)
628
629 out_file.write(self._UNMARSHAL_VALUE % {'old_type': self.old_type})
630
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700631 if self.supported_values:
632 out_file.write(self._CHECK_SUPPORTED_VALUES %
Vadim Bendeburyb85286c2015-09-15 14:25:48 -0700633 {'supported_values': self.supported_values,
634 'error_code': self.error_code})
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700635 if self.conditional_value:
636 out_file.write(
637 self._CHECK_CONDITIONAL % {'name': self.conditional_value,
638 'error_code': self.error_code})
639 # Checking for valid values.
640 if len(self.valid_values)+len(self.bounds) > 0:
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700641 if len(self.valid_values) > 0:
642 out_file.write(self._VALUE_START_SWITCH % {'name': '*target'})
643 for value in self.valid_values:
644 if self._NeedsIfdef():
645 out_file.write(self._VALUE_CASE_IFDEF % {'value': value})
646 else:
647 out_file.write(self._VALUE_CASE % {'value': value})
648 out_file.write(self._VALUE_END_SWITCH)
649 for (lower, upper) in self.bounds:
650 out_file.write(
651 self._CHECK_BOUND % {'lower': lower, 'upper': upper})
652 out_file.write(self._CHECK_VALUES_END % {'error_code': self.error_code})
653
654 out_file.write(self._UNMARSHAL_END)
655 marshalled_types.add(self.new_type)
656
657 def OutputMarshalDecl(self, out_file, declared_types, typemap):
658 """Writes marshal declarations for Interface to |out_file|.
659
660 Outputted declaration depends on whether Interface type has a
661 conditionally valid value.
662
663 Args:
664 out_file: The output file.
665 declared_types: A set of types for which marshal and unmarshal function
666 declarations have already been generated.
667 typemap: A dict mapping type names to the corresponding object.
668 """
669 if self.new_type in declared_types:
670 return
671 if self.old_type not in declared_types:
672 typemap[self.old_type].OutputMarshalDecl(
673 out_file, declared_types, typemap)
674 if self.HasConditional():
675 out_file.write(
676 self._CONDITIONAL_MARSHAL_DECLARATION % {'type': self.new_type})
677 else:
678 out_file.write(self._MARSHAL_DECLARATION % {'type': self.new_type})
679 declared_types.add(self.new_type)
680
681 def OutputUnmarshalCall(
682 self, out_file, field_type, field_name, conditional_valid):
683 """Write a call to Unmarshal function for Interface type to |out_file|.
684
685 Override TPMType OutputUnmarshalCall because when an Interface type has
686 a conditionally valid value, a BOOL value (|conditional_valid|) is passed
687 as a parameter.
688
689 Args:
690 out_file: The output file.
691 field_type: The type of the field in 'target' struct to be unmarshalled.
692 field_name: The name of the field in 'target' struct to be unmarshalled.
693 conditional_valid: BOOL value passed to function call indicating if
694 Interface conditional_value is valid.
695 """
696 if self.conditional_value:
697 out_file.write(
698 self._CONDITIONAL_UNMARSHAL_CALL % {'type': field_type,
699 'name': field_name,
700 'flag': conditional_valid})
701 else:
702 out_file.write(self._UNMARSHAL_CALL % {'type': field_type,
703 'name': field_name})
704
705class Structure(TPMType):
706 """Represents a TPM structure.
707
708 Attributes:
709 name: The name of the structure.
710 fields: A list of Field objects representing struct fields.
711 upper_bounds: A dictionary of (name, val) tuples mapping name to max val.
712 lower_bounds: A dictionary of (name, val) tuples mapping name to min val.
713 size_check: Set if TPM2B structure must be size checked (triggered by size=)
714 valid_tag_values: A list of values field tag is allowed to take.
715 error_code: The return code to be returned if an error occurs
716 """
717 _STRUCTURE_MARSHAL_START = """
718UINT16 %(name)s_Marshal(
719 %(name)s *source,
720 BYTE **buffer,
721 INT32 *size) {
722 UINT16 total_size = 0;"""
723 _STRUCTURE_UNMARSHAL_START = """
724TPM_RC %(name)s_Unmarshal(
725 %(name)s *target,
726 BYTE **buffer,
727 INT32 *size) {
728 TPM_RC result;"""
729 _MARSHAL_END = '\n return total_size;\n}\n'
Jocelyn Bohrfb668122015-07-30 10:17:56 -0700730 _SETUP_ARRAY_FIELD = '\n INT32 i;'
731 _CHECK_SIZE_START = """
732 UINT32 start_size = *size;
733 UINT32 struct_size;"""
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700734 _CHECK_SIZE_END = """
Jocelyn Bohrfb668122015-07-30 10:17:56 -0700735 struct_size = start_size - *size - sizeof(target->t.size);
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700736 if (struct_size != target->t.size) {
737 return TPM_RC_SIZE;
738 }"""
739 _TPM2B_ZERO_SIZE = """
740 if (target->t.size == 0) {
741 return %(return_value)s;
742 }"""
743 _CHECK_BOUND = """
744 if (target->%(name)s %(operator)s %(bound_value)s) {
745 return %(error_code)s;
746 }"""
747
748 def __init__(self, name):
749 """Initializes a Structure instance.
750
751 Initially the instance will have no fields, upper_bounds, lower_bounds, or
752 valid_tag_values. Those can be added with AddField(), AddUpperBound(),
753 AddLowerBound(), and AddTagVal() methods.
754
755 Args:
756 name: The name of the structure.
757 """
758 self.name = name
759 self.fields = []
760 self.upper_bounds = {}
761 self.lower_bounds = {}
762 self.size_check = False
763 self.valid_tag_values = []
764 self.error_code = 'TPM_RC_VALUE'
765
766 class Field(object):
767 """Represents a field in TPM structure
768
769 Attributes:
770 field_type: The type of field.
771 field_name: The name of the field.
772 extra_argument: Argument passed to OutputMarshalCall. Value represents a
773 BOOL value, selector value, or array length depending on context.
774 is_array: Boolean indicating whether field is an array.
775 """
776 _MARSHAL_FIELD_ARRAY = """
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700777 for (i = 0; i < source->%(array_length)s; ++i) {
778 total_size += %(type)s_Marshal(
779 &source->%(name)s[i], buffer, size);
780 }"""
781 _UNMARSHAL_FIELD_ARRAY = """
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700782 for (i = 0; i < target->%(array_length)s; ++i) {
783 result = %(type)s_Unmarshal(
784 &target->%(name)s[i], buffer, size);
785 if (result != TPM_RC_SUCCESS) {
786 return result;
787 }
788 }"""
789 def __init__(self, field_type, field_name, extra_argument, is_array):
790 """Initializes a Structure.Field instance.
791
792 Initially the instance will have no fields, upper_bounds, lower_bounds, or
793 valid_tag_values. Those can be added with AddField(), AddUpperBound(),
794 AddLowerBound(), and AddTagVal() methods.
795
796 Args:
797 field_type: The type of field.
798 field_name: The name of the field.
799 extra_argument: Argument passed to OutputMarshalCall. Value represents a
800 BOOL value, selector value, or array length depending on context.
801 is_array: Boolean indicating whether field is an array.
802 """
803 self.field_type = field_type
804 self.field_name = field_name
805 self.extra_argument = extra_argument
806 self.is_array = is_array
807
808 def OutputMarshal(self, out_file, typemap):
809 """Write a call to marshal the field this instance represents.
810
811 Args:
812 out_file: The output file.
813 typemap: A dict mapping type names to the corresponding object.
814 """
815 if self.is_array:
816 out_file.write(
817 self._MARSHAL_FIELD_ARRAY % {'type': self.field_type,
818 'name': self.field_name,
819 'array_length': self.extra_argument})
820 else:
821 typemap[self.field_type].OutputMarshalCall(
822 out_file, self.field_type, self.field_name, self.extra_argument)
823
824 def OutputUnmarshal(self, out_file, typemap):
825 """Write a call to unmarshal the field this instance represents.
826
827 Args:
828 out_file: The output file.
829 typemap: A dict mapping type names to the corresponding object.
830 """
831 if self.is_array:
832 out_file.write(
833 self._UNMARSHAL_FIELD_ARRAY % {'type': self.field_type,
834 'name': self.field_name,
835 'array_length': self.extra_argument})
836 else:
837 typemap[self.field_type].OutputUnmarshalCall(
838 out_file, self.field_type, self.field_name, self.extra_argument)
839
840 def AddField(self, field_type, field_name, extra_argument, is_array):
841 """Adds a field to fields attribute in Structure.
842
843 Args:
844 field_name: The name of the field.
845 field_type: The type of field.
846 extra_argument: Argument passed to OutputMarshalCall. Value represents a
847 BOOL value, selector value, or array length depending on context.
848 is_array: Boolean indicating whether field is an array.
849 """
850 # Each TPM2B is a union of two sized buffers, one which is type specific
851 # (the 't' element) and the other is a generic value (the 'b' element). For
852 # this reason a 't.' is prepended for fields in a TPM2B type. See section
853 # 9.11.6 in TCG TPM2.0 Library Specification, Part 2: Structures for more
854 # details.
855 if IsTPM2B(self.name):
856 field_name = 't.' + field_name
857 if is_array:
858 extra_argument = 't.' + extra_argument
859 self.fields.append(
860 self.Field(field_type, field_name, extra_argument, is_array))
861
862 def AddUpperBound(self, field_name, value):
863 """Adds an upper bound for a field.
864
865 Args:
866 field_name: Name of field with bound.
867 value: Value of upper bound.
868 """
869 if IsTPM2B(self.name):
870 field_name = 't.' + field_name
871 self.upper_bounds[field_name] = value
872
873 def AddLowerBound(self, field_name, value):
874 """Adds a lower bound for a field.
875
876 Args:
877 field_name: Name of field with bound.
878 value: Value of lower bound.
879 """
880 if IsTPM2B(self.name):
881 field_name = 't.' + field_name
882 self.lower_bounds[field_name] = value
883
884 def AddTagValue(self, value):
885 """Adds a valid value for tag field.
886
887 Args:
888 value: Valid value for tag field.
889 """
890 self.valid_tag_values.append(value)
891
892 def _GetFieldTypes(self):
893 """Creates a set which holds all current field types.
894
895 Returns:
896 A set of field types.
897 """
898 return set([field.field_type for field in self.fields])
899
900 def OutputMarshalImpl(self, out_file, marshalled_types, typemap):
901 """Writes marshal implementations for Structure to |out_file|.
902
903 Args:
904 out_file: The output file.
905 marshalled_types: A set of types for which marshal and unmarshal functions
906 have already been generated.
907 typemap: A dict mapping type names to the corresponding object.
908 """
909 if self.name in marshalled_types:
910 return
911 # Make sure any dependencies already have marshal functions defined.
912 for field_type in self._GetFieldTypes():
913 if field_type not in marshalled_types:
914 typemap[field_type].OutputMarshalImpl(
915 out_file, marshalled_types, typemap)
916 marshalled_types.add(field_type)
917
918 out_file.write(self._STRUCTURE_MARSHAL_START % {'name': self.name})
Jocelyn Bohrfb668122015-07-30 10:17:56 -0700919 # If any field is an array, create local variable INT32 i.
920 for field in self.fields:
921 if field.is_array:
922 out_file.write(self._SETUP_ARRAY_FIELD)
923 break
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700924 for field in self.fields:
925 field.OutputMarshal(out_file, typemap)
926 out_file.write(self._MARSHAL_END)
927
928 out_file.write(self._STRUCTURE_UNMARSHAL_START % {'name': self.name})
929 if self.size_check:
930 out_file.write(self._CHECK_SIZE_START)
Jocelyn Bohrfb668122015-07-30 10:17:56 -0700931 # If any field is an array, create local variable INT32 i.
932 for field in self.fields:
933 if field.is_array:
934 out_file.write(self._SETUP_ARRAY_FIELD)
935 break
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700936 for field in self.fields:
937 field.OutputUnmarshal(out_file, typemap)
938 return_value = self.error_code
939 if field.field_name == 't.size' and self.size_check:
940 out_file.write(self._TPM2B_ZERO_SIZE % {'return_value': 'TPM_RC_SIZE'})
941 if field.field_name == 't.size' and not self.size_check:
942 out_file.write(
943 self._TPM2B_ZERO_SIZE % {'return_value': 'TPM_RC_SUCCESS'})
944 if field.field_name in self.upper_bounds:
945 if (field.field_name == 'count' or
946 field.field_name == 't.size' or
947 field.field_name == 'size'):
948 return_value = 'TPM_RC_SIZE'
949 out_file.write(self._CHECK_BOUND %
Vadim Bendeburyb85286c2015-09-15 14:25:48 -0700950 {'name': field.field_name,
951 'operator': '>',
952 'bound_value': self.upper_bounds[field.field_name],
953 'error_code': return_value})
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700954 if field.field_name in self.lower_bounds:
955 if (field.field_name == 'count' or
956 field.field_name == 't.size' or
957 field.field_name == 'size'):
958 return_value = 'TPM_RC_SIZE'
959 out_file.write(self._CHECK_BOUND %
Vadim Bendeburyb85286c2015-09-15 14:25:48 -0700960 {'name': field.field_name,
961 'operator': '<',
962 'bound_value': self.lower_bounds[field.field_name],
963 'error_code': return_value})
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700964 if field.field_name == 'tag' and len(self.valid_tag_values) != 0:
965 out_file.write(self._VALUE_START_SWITCH % {'name': 'target->tag'})
966 for value in self.valid_tag_values:
967 out_file.write(self._VALUE_CASE % {'value': value})
968 out_file.write(self._VALUE_END_SWITCH % {'error_code': 'TPM_RC_TAG'})
969 if self.size_check:
970 out_file.write(self._CHECK_SIZE_END)
971 out_file.write(self._UNMARSHAL_END)
972
973 marshalled_types.add(self.name)
974
Vadim Bendeburyb85286c2015-09-15 14:25:48 -0700975 def OutputMarshalDecl(self, out_file, declared_types, _):
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700976 """Writes marshal declarations for Structure to |out_file|.
977
978 Args:
979 out_file: The output file.
980 declared_types: A set of types for which marshal and unmarshal function
981 declarations have already been generated.
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700982 """
Vadim Bendeburyb85286c2015-09-15 14:25:48 -0700983 self._OutputStructOrUnionMarshalDecl(out_file, declared_types)
ChromeOS Developer9edfbac2015-07-17 16:33:16 -0700984
985class Union(TPMType):
986 """Represents a TPM union.
987
988 Attributes:
989 name: The name of the union.
990 fields: A list of Field objects representing union fields.
991 """
992
993 _UNION_MARSHAL_START = """
994UINT16 %(name)s_Marshal(
995 %(name)s *source,
996 BYTE **buffer,
997 INT32 *size,
998 UINT32 selector) {
999 switch(selector) {"""
1000 _UNION_UNMARSHAL_START = """
1001TPM_RC %(name)s_Unmarshal(
1002 %(name)s *target,
1003 BYTE **buffer,
1004 INT32 *size,
1005 UINT32 selector) {
1006 switch(selector) {"""
1007 _MARSHAL_END = '\n }\n return 0;\n}\n'
1008 _UNMARSHAL_END = '\n }\n return TPM_RC_SELECTOR;\n}\n'
1009 _MARSHAL_DECLARATION = """
1010UINT16 %(type)s_Marshal(
1011 %(type)s *source,
1012 BYTE **buffer,
1013 INT32 *size,
1014 UINT32 selector);
1015
1016TPM_RC %(type)s_Unmarshal(
1017 %(type)s *target,
1018 BYTE **buffer,
1019 INT32 *size,
1020 UINT32 selector);
1021"""
Jocelyn Bohr5aef9c62015-08-11 12:46:22 -07001022 _CASE_SELECTOR = """
1023 case %(selector)s:"""
1024 _MARSHAL_EMPTY = """
1025 return 0;"""
1026 _UNMARSHAL_EMPTY = """
1027 return TPM_RC_SUCCESS;"""
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001028 _MARSHAL_FIELD = """
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001029 return %(type)s_Marshal(
1030 (%(type)s*)&source->%(name)s, buffer, size);"""
1031 _UNMARSHAL_FIELD = """
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001032 return %(type)s_Unmarshal(
1033 (%(type)s*)&target->%(name)s, buffer, size);"""
1034 _SETUP_MARSHAL_FIELD_ARRAY = """
1035 INT32 i;
1036 UINT16 total_size = 0;"""
1037 _SETUP_UNMARSHAL_FIELD_ARRAY = """
1038 INT32 i;
1039 TPM_RC result = TPM_RC_SUCCESS;"""
1040 _MARSHAL_FIELD_ARRAY = """
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001041 for (i = 0; i < %(array_length)s; ++i) {
1042 total_size += %(type)s_Marshal(
1043 &source->%(name)s[i], buffer, size);
1044 }
1045 return total_size;"""
1046 _UNMARSHAL_FIELD_ARRAY = """
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001047 for (i = 0; i < %(array_length)s; ++i) {
1048 result = %(type)s_Unmarshal(
1049 &target->%(name)s[i], buffer, size);
1050 if (result != TPM_RC_SUCCESS) {
1051 return result;
1052 }
1053 }
1054 return TPM_RC_SUCCESS;"""
1055 _UNMARSHAL_FIELD_CONDITIONAL = """
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001056 return %(type)s_Unmarshal(
1057 &target->%(name)s, buffer, size, FALSE);"""
1058 _UNION_MARSHAL_CALL = """
1059 total_size += %(type)s_Marshal(
1060 &source->%(name)s, buffer, size, source->%(selector)s);"""
1061 _UNION_UNMARSHAL_CALL = """
1062 result = %(type)s_Unmarshal(
1063 &target->%(name)s, buffer, size, target->%(selector)s);
1064 if (result != TPM_RC_SUCCESS) {
1065 return result;
1066 }"""
1067 _IFDEF = '\n#ifdef %(type)s'
1068 _ENDIF = '\n#endif'
1069 _IFDEF_TYPE_RE = re.compile(r'^TPM_(ALG|CC).*')
1070 # Represents a field in a TPM union.
1071 Field = collections.namedtuple(
1072 'Field', ['field_type', 'field_name', 'array_length'])
1073
1074 def __init__(self, name):
1075 """Initializes a Union instance.
1076
1077 Initially the instance will have no fields. Fields are added with the
1078 AddField() method.
1079
1080 Args:
1081 name: The name of the structure.
1082 """
1083 self.name = name
1084 self.fields = []
1085
1086 def _NeedsIfdef(self, selector):
1087 """Returns True if selector is a type which needs ifdef enclosing."""
1088 return self._IFDEF_TYPE_RE.search(selector)
1089
1090 def AddField(self, field_type, field_name, array_length):
1091 """Adds a field to fields attribute in Union.
1092
1093 Args:
1094 field_name: The name of the field.
1095 field_type: The type of field.
1096 array_length: Length of array if field is an array type. None if not an
1097 array type.
1098 """
Jocelyn Bohr7cba2332015-08-10 16:28:31 -07001099 # xor is a C++ keyword and must be fixed.
1100 if field_name == 'xor':
1101 field_name = 'xor_'
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001102 self.fields.append(self.Field(field_type, field_name, array_length))
1103
1104 def _OutputMarshalField(
Vadim Bendeburyb85286c2015-09-15 14:25:48 -07001105 self, out_file, field_type, field_name, array_length):
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001106 """Write a call to marshal a field in this union.
1107
1108 Args:
1109 out_file: The output file.
1110 field_name: The name of the field.
1111 field_type: The type of field.
1112 array_length: Variable indicating length of array, None if field is not
1113 an array.
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001114 """
1115 if array_length:
1116 out_file.write(self._MARSHAL_FIELD_ARRAY % {'type': field_type,
1117 'name': field_name,
Jocelyn Bohr5aef9c62015-08-11 12:46:22 -07001118 'array_length': array_length})
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001119 else:
1120 out_file.write(self._MARSHAL_FIELD % {'type': field_type,
Jocelyn Bohr5aef9c62015-08-11 12:46:22 -07001121 'name': field_name})
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001122
1123 def _OutputUnmarshalField(
Vadim Bendeburyb85286c2015-09-15 14:25:48 -07001124 self, out_file, field_type, field_name, array_length, typemap):
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001125 """Write a call to unmarshal a field in this union.
1126
1127 Args:
1128 out_file: The output file.
1129 field_name: The name of the field.
1130 field_type: The type of field.
1131 array_length: Variable indicating length of array, None if field is not
1132 an array.
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001133 typemap: A dict mapping type names to the corresponding object.
1134 """
1135 if array_length:
1136 out_file.write(
1137 self._UNMARSHAL_FIELD_ARRAY % {'type': field_type,
1138 'name': field_name,
Jocelyn Bohr5aef9c62015-08-11 12:46:22 -07001139 'array_length': array_length})
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001140 elif typemap[field_type].HasConditional():
1141 out_file.write(
1142 self._UNMARSHAL_FIELD_CONDITIONAL % {'type': field_type,
Jocelyn Bohr5aef9c62015-08-11 12:46:22 -07001143 'name': field_name})
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001144 else:
1145 out_file.write(self._UNMARSHAL_FIELD % {'type': field_type,
Jocelyn Bohr5aef9c62015-08-11 12:46:22 -07001146 'name': field_name})
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001147
1148 def OutputMarshalImpl(self, out_file, marshalled_types, typemap):
1149 """Writes marshal implementations for Union to |out_file|.
1150
1151 Args:
1152 out_file: The output file.
1153 marshalled_types: A set of types for which marshal and unmarshal functions
1154 have already been generated.
1155 typemap: A dict mapping type names to the corresponding object.
1156 """
1157 if (self.name in marshalled_types or
1158 self.name == 'TPMU_NAME' or
1159 self.name == 'TPMU_ENCRYPTED_SECRET'):
1160 return
1161 selector_values = union_selectors.GetUnionSelectorValues(self.name)
1162 field_types = {f.field_name: f.field_type for f in self.fields}
1163 array_lengths = {f.field_name: f.array_length for f in self.fields}
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001164 # Make sure any dependencies already have marshal functions defined.
1165 for field_name in field_types:
1166 field_type = field_types[field_name]
1167 if field_type not in marshalled_types:
1168 typemap[field_type].OutputMarshalImpl(
1169 out_file, marshalled_types, typemap)
1170 marshalled_types.add(field_type)
Vadim Bendeburye6c58e42015-09-08 12:55:42 -07001171 out_file.write(self._UNION_MARSHAL_START % {'name': self.name})
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001172 # Set up variables if Union is an array type.
1173 if self.fields[0].array_length:
1174 out_file.write(self._SETUP_MARSHAL_FIELD_ARRAY)
1175 for selector in selector_values:
1176 field_name = union_selectors.GetUnionSelectorField(self.name, selector)
Jocelyn Bohr5aef9c62015-08-11 12:46:22 -07001177 if self._NeedsIfdef(selector):
1178 out_file.write(self._IFDEF % {'type': selector})
1179 out_file.write(self._CASE_SELECTOR % {'selector':selector})
1180 # Selector is not associated with a name, so no marshaling occurs.
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001181 if not field_name:
Jocelyn Bohr5aef9c62015-08-11 12:46:22 -07001182 out_file.write(self._MARSHAL_EMPTY)
1183 if self._NeedsIfdef(selector):
1184 out_file.write(self._ENDIF)
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001185 continue
1186 field_type = field_types[field_name]
1187 array_length = array_lengths[field_name]
Vadim Bendeburyb85286c2015-09-15 14:25:48 -07001188 self._OutputMarshalField(out_file, field_type, field_name, array_length)
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001189 if self._NeedsIfdef(selector):
1190 out_file.write(self._ENDIF)
1191 out_file.write(self._MARSHAL_END)
1192 out_file.write(self._UNION_UNMARSHAL_START % {'name': self.name})
1193 # Set up variables if Union is an array type.
1194 if self.fields[0].array_length:
1195 out_file.write(self._SETUP_UNMARSHAL_FIELD_ARRAY)
1196 for selector in selector_values:
1197 field_name = union_selectors.GetUnionSelectorField(self.name, selector)
Jocelyn Bohr5aef9c62015-08-11 12:46:22 -07001198 if self._NeedsIfdef(selector):
1199 out_file.write(self._IFDEF % {'type': selector})
1200 out_file.write(self._CASE_SELECTOR % {'selector': selector})
1201 # Selector is not associated with a name, so no unmarshaling occurs.
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001202 if not field_name:
Jocelyn Bohr5aef9c62015-08-11 12:46:22 -07001203 out_file.write(self._UNMARSHAL_EMPTY)
1204 if self._NeedsIfdef(selector):
1205 out_file.write(self._ENDIF)
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001206 continue
1207 field_type = field_types[field_name]
1208 array_length = array_lengths[field_name]
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001209 self._OutputUnmarshalField(
Vadim Bendeburyb85286c2015-09-15 14:25:48 -07001210 out_file, field_type, field_name, array_length, typemap)
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001211 if self._NeedsIfdef(selector):
1212 out_file.write(self._ENDIF)
1213 out_file.write(self._UNMARSHAL_END)
1214 marshalled_types.add(self.name)
1215
Vadim Bendeburyb85286c2015-09-15 14:25:48 -07001216 def OutputMarshalDecl(self, out_file, declared_types, _):
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001217 """Writes marshal declarations for Union to |out_file|.
1218
1219 Args:
1220 out_file: The output file.
1221 declared_types: A set of types for which marshal and unmarshal function
1222 declarations have already been generated.
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001223 """
Vadim Bendeburyb85286c2015-09-15 14:25:48 -07001224 self._OutputStructOrUnionMarshalDecl(out_file, declared_types)
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001225
1226 def OutputMarshalCall(self, out_file, field_type, field_name, selector):
1227 """Write a call to marshal function for Union type to |out_file|.
1228
1229 Override TPMType OutputMarshalCall to pass in selector value.
1230
1231 Args:
1232 out_file: The output file.
1233 field_type: The type of the field in 'target' struct to be unmarshalled.
1234 field_name: The name of the field in 'target' struct to be unmarshalled.
1235 selector: The name of the selector value.
1236 """
1237 out_file.write(self._UNION_MARSHAL_CALL % {'type': field_type,
1238 'name': field_name,
1239 'selector': selector})
1240
1241 def OutputUnmarshalCall(self, out_file, field_type, field_name, selector):
1242 """Write a call to unmarshal function for Union type to |out_file|.
1243
1244 Override TPMType OutputUnmashalCall to pass in selector value.
1245
1246 Args:
1247 out_file: The output file.
1248 field_type: The type of the field in 'target' struct to be unmarshalled.
1249 field_name: The name of the field in 'target' struct to be unmarshalled.
1250 selector: The name of the selector value.
1251 """
1252 out_file.write(self._UNION_UNMARSHAL_CALL % {'type': field_type,
1253 'name': field_name,
1254 'selector': selector})
1255
1256class StructureParser(object):
1257 """Structure definition parser.
1258
1259 The input text file is extracted from the PDF file containing the TPM
1260 structures specification from the Trusted Computing Group. The syntax
1261 of the text file is defined by extract_structures.sh.
1262
1263 - Parses typedefs to a list of Typedef objects.
1264 - Parses constants to a list of ConstantType objects.
1265 - Parses attribute structures to a list of AttributeStruct objects.
1266 - Parses interfaces to a list of Interface objects.
1267 - Parses structs to a list of Structure objects.
1268 - Parses unions to a list of Union objects
1269
1270 The parser also creates 'typemap' dict which maps every type to its generator
1271 object. This typemap helps manage type dependencies.
1272
1273 Example usage:
1274 parser = StructureParser(open('myfile'))
1275 types, typemap = parser.Parse()
1276 """
1277
1278 # Compile regular expressions.
1279 _BEGIN_TYPES_TOKEN = '_BEGIN_TYPES'
1280 _BEGIN_CONSTANTS_TOKEN = '_BEGIN_CONSTANTS'
1281 _BEGIN_ATTRIBUTE_STRUCTS_TOKEN = '_BEGIN_ATTRIBUTE_STRUCTS'
1282 _BEGIN_INTERFACES_TOKEN = '_BEGIN_INTERFACES'
1283 _BEGIN_STRUCTURES_TOKEN = '_BEGIN_STRUCTURES'
1284 _BEGIN_UNIONS_TOKEN = '_BEGIN_UNIONS'
1285 _BEGIN_DEFINES_TOKEN = '_BEGIN_DEFINES'
1286 _END_TOKEN = '_END'
1287 _OLD_TYPE_RE = re.compile(r'^_OLD_TYPE\s+(\w+)$')
1288 _NEW_TYPE_RE = re.compile(r'^_NEW_TYPE\s+(\w+)$')
1289 _STRUCTURE_RE = re.compile(r'^_STRUCTURE\s+(\w+)$')
1290 _UNION_RE = re.compile(r'^_UNION\s+(\w+)$')
1291 _TYPE_RE = re.compile(r'^_TYPE\s+(\w+)$')
1292 _NAME = r'[a-zA-Z0-9_()\[\]/\*\+\-]+'
1293 _NAME_RE = re.compile(r'^_NAME\s+([a-zA-Z0-9_()/]+)$')
1294 _SUBSTITUTE_RE = re.compile(r'^_SUBSTITUTE\s+([a-zA-Z0-9_()/]+)$')
1295 _CONDITIONAL_RE = re.compile(r'^_CONDITIONAL\s+([a-zA-Z0-9_()/]+)$')
1296 _MIN_RE = re.compile(r'^_MIN\s+([a-zA-Z0-9_()/]+)$')
1297 _MAX_RE = re.compile(r'^_MAX\s+([a-zA-Z0-9_()/]+)$')
1298 _RETURN_RE = re.compile(r'^_RETURN\s+([a-zA-Z0-9_()/]+)$')
1299 _RESERVED_RE = re.compile(r'^_RESERVED\s+([a-zA-Z0-9_()/]+)$')
1300
1301 # Regular expressions for structures.
1302 _NAME_UNION_RE = re.compile(
1303 r'^_NAME\s+([a-zA-Z0-9_()/]+)\s+_UNION\s+([a-zA-Z0-9_()/]+)$')
1304 _NAME_ARRAY_RE = re.compile(
1305 r'^_NAME\s+([a-zA-Z0-9_()/]+)\s+_ARRAY\s+([a-zA-Z0-9_()/]+)$')
1306 _NAME_PLUS_RE = re.compile(r'^_NAME\s+([a-zA-Z0-9_()\[\]/\*\+\-]+)\s+_PLUS$')
1307 _VALID_RE = re.compile(r'^_VALID\s+([a-zA-Z0-9_()\[\]/\*\+\-]+)$')
1308 _FIELD_MAX_RE = re.compile(
1309 r'^_MAX\s+([a-zA-Z0-9_()/]+)\s+([a-zA-Z0-9_()/]+)$')
1310 _FIELD_MIN_RE = re.compile(
1311 r'^_MIN\s+([a-zA-Z0-9_()/]+)\s+([a-zA-Z0-9_()/]+)$')
1312 _NAME_SIZE_CHECK_RE = re.compile(r'^_NAME size _CHECK$')
1313
1314 def __init__(self, in_file):
1315 """Initializes a StructureParser instance.
1316
1317 Args:
1318 in_file: A file as returned by open() which has been opened for reading.
1319 """
1320 self._line = None
1321 self._in_file = in_file
1322
1323 def _NextLine(self):
1324 """Gets the next input line.
1325
1326 Returns:
1327 # The next input line if another line is available, None otherwise.
1328 """
1329 try:
1330 self._line = self._in_file.next()
1331 except StopIteration:
1332 self._line = None
1333
1334 def Parse(self):
1335 """Parse everything in a structures file.
1336
1337 Returns:
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001338 A type-map as described in the class documentation.
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001339 """
1340 self._NextLine()
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001341 typemap = {}
1342 # maps types to valid constants
1343 while self._line:
1344 if self._BEGIN_TYPES_TOKEN == self._line.rstrip():
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001345 self._ParseTypes(typemap)
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001346 elif self._BEGIN_CONSTANTS_TOKEN == self._line.rstrip():
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001347 self._ParseConstants(typemap)
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001348 elif self._BEGIN_ATTRIBUTE_STRUCTS_TOKEN == self._line.rstrip():
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001349 self._ParseAttributeStructs(typemap)
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001350 elif self._BEGIN_INTERFACES_TOKEN == self._line.rstrip():
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001351 self._ParseInterfaces(typemap)
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001352 elif self._BEGIN_STRUCTURES_TOKEN == self._line.rstrip():
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001353 self._ParseStructures(typemap)
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001354 elif self._BEGIN_UNIONS_TOKEN == self._line.rstrip():
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001355 self._ParseUnions(typemap)
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001356 else:
1357 print('Invalid file format: %s' % self._line)
1358 break
1359 self._NextLine()
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001360 return typemap
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001361
1362 def _ParseTypes(self, typemap):
1363 """Parses a typedefs section.
1364
1365 The current line should be _BEGIN_TYPES and the method will stop parsing
1366 when an _END line is found.
1367
1368 Args:
1369 typemap: A dictionary to which parsed types are added.
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001370 """
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001371 self._NextLine()
1372 while self._END_TOKEN != self._line.rstrip():
1373 match = self._OLD_TYPE_RE.search(self._line)
1374 if not match:
1375 print('Invalid old type: %s' % self._line)
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001376 return
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001377 old_type = match.group(1)
1378 self._NextLine()
1379 match = self._NEW_TYPE_RE.search(self._line)
1380 if not match:
1381 print('Invalid new type: %s' % self._line)
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001382 return
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001383 new_type = match.group(1)
1384 self._NextLine()
1385 # We don't need code for BOOL type to be generated.
1386 if new_type == 'BOOL':
1387 continue
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001388 typemap[new_type] = Typedef(old_type, new_type)
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001389
1390 def _ParseConstants(self, typemap):
1391 """Parses a constants section.
1392
1393 The current line should be _BEGIN_CONSTANTS and the method will stop parsing
1394 when an _END line is found. Each group of constants has an associated type
1395 alias.
1396
1397 Args:
1398 typemap: A dictionary to which parsed types are added.
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001399 """
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001400 self._NextLine()
1401 while self._END_TOKEN != self._line.rstrip():
1402 match_old = self._OLD_TYPE_RE.search(self._line)
1403 if not match_old:
1404 print('Invalid constants section, expected OLD_TYPE: %s' % self._line)
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001405 return
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001406 old_type = match_old.group(1)
1407 self._NextLine()
1408 match_new = self._NEW_TYPE_RE.search(self._line)
1409 if not match_new:
1410 print('Invalid constants section, expected NEW_TYPE: %s' % self._line)
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001411 return
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001412 new_type = match_new.group(1)
1413 self._NextLine()
1414 current_constant_type = ConstantType(old_type, new_type)
1415 match_name = self._NAME_RE.search(self._line)
1416 if not match_name:
1417 print('Invalid constant name: %s' % self._line)
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001418 return
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001419 while match_name:
1420 name = match_name.group(1)
1421 current_constant_type.valid_values.append(name)
1422 self._NextLine()
1423 match_name = self._NAME_RE.search(self._line)
1424 match_return = self._RETURN_RE.search(self._line)
1425 if not match_return:
1426 print('Invalid constants section, expected RETURN: %s' % self._line)
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001427 return
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001428 current_constant_type.error_code = match_return.group(1)
1429 self._NextLine()
1430 # We don't need code for TPM_PS type to be generated.
1431 if new_type == 'TPM_PS':
1432 continue
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001433 typemap[new_type] = current_constant_type
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001434
1435 def _ParseAttributeStructs(self, typemap):
1436 """Parses an attribute structs section.
1437
1438 The current line should be _BEGIN_ATTRIBUTE_STRUCTS and the method will
1439 stop parsing when an _END line is found. Each attribute structure has an
1440 associated type alias.
1441
1442 Args:
1443 typemap: A dictionary to which parsed types are added.
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001444 """
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001445 self._NextLine()
1446 while self._END_TOKEN != self._line.rstrip():
1447 match_old = self._OLD_TYPE_RE.search(self._line)
1448 if not match_old:
1449 print('Invalid attributes section, expected OLD_TYPE: %s' % self._line)
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001450 return
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001451 old_type = match_old.group(1)
1452 self._NextLine()
1453 match_new = self._NEW_TYPE_RE.search(self._line)
1454 if not match_new:
1455 print('Invalid attributes section, expected NEW_TYPE: %s' % self._line)
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001456 return
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001457 new_type = match_new.group(1)
1458 self._NextLine()
1459 current_attribute_struct = AttributeStructure(old_type, new_type)
1460 match_reserved = self._RESERVED_RE.search(self._line)
1461 while match_reserved:
1462 bits = match_reserved.group(1)
1463 current_attribute_struct.reserved.append(bits)
1464 self._NextLine()
1465 match_reserved = self._RESERVED_RE.search(self._line)
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001466 typemap[new_type] = current_attribute_struct
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001467
1468 def _ParseInterfaces(self, typemap):
1469 """Parses an interface types section.
1470
1471 The current line should be _BEGIN_INTERFACES and the method will stop
1472 parsing when an _END line is found. Each interface type has an associated
1473 type alias.
1474
1475 Args:
1476 typemap: A dictionary to which parsed types are added.
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001477 """
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001478 self._NextLine()
1479 while self._END_TOKEN != self._line.rstrip():
1480 match_old = self._OLD_TYPE_RE.search(self._line)
1481 if not match_old:
1482 print('Invalid interfaces section, expected OLD_TYPE: %s' % self._line)
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001483 return
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001484 old_type = match_old.group(1)
1485 self._NextLine()
1486 match_new = self._NEW_TYPE_RE.search(self._line)
1487 if not match_new:
1488 print('Invalid interfaces section, expected NEW_TYPE: %s' % self._line)
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001489 return
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001490 new_type = match_new.group(1)
1491 self._NextLine()
1492 current_interface = Interface(old_type, new_type)
1493 while True:
1494 match_name = self._NAME_RE.search(self._line)
1495 match_conditional_value = self._CONDITIONAL_RE.search(self._line)
1496 match_min = self._MIN_RE.search(self._line)
1497 match_return = self._RETURN_RE.search(self._line)
1498 match_supported_values = self._SUBSTITUTE_RE.search(self._line)
1499 if match_name:
1500 current_interface.valid_values.append(match_name.group(1))
1501 elif match_supported_values:
1502 current_interface.supported_values = match_supported_values.group(1)
1503 elif match_min:
1504 lower = match_min.group(1)
1505 self._NextLine()
1506 match_max = self._MAX_RE.search(self._line)
1507 if not match_max:
1508 print('Invalid interfaces section, expected _MAX: %s' % self._line)
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001509 return
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001510 upper = match_max.group(1)
1511 current_interface.bounds.append((lower, upper))
1512 elif match_conditional_value:
1513 current_interface.conditional_value = match_conditional_value.group(1)
1514 elif match_return:
1515 current_interface.error_code = match_return.group(1)
1516 self._NextLine()
1517 break
1518 else:
1519 print('Invalid interfaces section: %s' % self._line)
1520 break
1521 self._NextLine()
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001522 typemap[new_type] = current_interface
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001523
1524 def _ParseStructures(self, typemap):
1525 """Parses a structures section.
1526
1527 The current line should be _BEGIN_STRUCTURES and the method will stop
1528 parsing when an _END line is found.
1529
1530 Args:
1531 typemap: A dictionary to which parsed types are added.
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001532 """
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001533 self._NextLine()
1534 while self._END_TOKEN != self._line.rstrip():
1535 match_structure = self._STRUCTURE_RE.search(self._line)
1536 if not match_structure:
1537 print('Invalid structure section, expected _STRUCTURE: %s' % self._line)
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001538 return
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001539 structure_name = match_structure.group(1)
1540 current_structure = Structure(structure_name)
1541 self._NextLine()
1542 match_type = self._TYPE_RE.search(self._line)
1543 if not match_type:
1544 print('Invalid field type: %s' % self._line)
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001545 return
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001546 while match_type:
1547 field_type = match_type.group(1)
1548 self._NextLine()
1549 match_name = self._NAME_RE.search(self._line)
1550 match_name_union = self._NAME_UNION_RE.search(self._line)
1551 match_name_array = self._NAME_ARRAY_RE.search(self._line)
1552 match_name_plus = self._NAME_PLUS_RE.search(self._line)
1553 match_name_size_check = self._NAME_SIZE_CHECK_RE.search(self._line)
1554 if match_name:
1555 field_name = match_name.group(1)
1556 current_structure.AddField(
1557 field_type, field_name, 'FALSE', False)
1558 self._NextLine()
1559 # Check for extra lines after tag field.
1560 if field_name == 'tag':
1561 match_valid = self._VALID_RE.search(self._line)
1562 if match_valid:
1563 while True:
1564 match_valid = self._VALID_RE.search(self._line)
1565 if match_valid:
1566 current_structure.AddTagValue(match_valid.group(1))
1567 self._NextLine()
1568 else:
1569 self._NextLine()
1570 break
1571 # Check for bounds.
1572 else:
1573 match_field_max = self._FIELD_MAX_RE.search(self._line)
1574 match_field_min = self._FIELD_MIN_RE.search(self._line)
1575 if match_field_max:
1576 current_structure.AddUpperBound(
1577 match_field_max.group(1), match_field_max.group(2))
1578 self._NextLine()
1579 elif match_field_min:
1580 current_structure.AddLowerBound(
1581 match_field_min.group(1), match_field_min.group(2))
1582 self._NextLine()
1583 elif match_name_union:
1584 field_name = match_name_union.group(1)
1585 selector = match_name_union.group(2)
1586 current_structure.AddField(
1587 field_type, field_name, selector, False)
1588 self._NextLine()
1589 elif match_name_array:
1590 field_name = match_name_array.group(1)
1591 array_length = match_name_array.group(2)
1592 current_structure.AddField(
1593 field_type, field_name, array_length, True)
1594 self._NextLine()
1595 # Check for bounds.
1596 match_field_max = self._FIELD_MAX_RE.search(self._line)
1597 match_field_min = self._FIELD_MIN_RE.search(self._line)
1598 if match_field_max:
1599 current_structure.AddUpperBound(
1600 match_field_max.group(1), match_field_max.group(2))
1601 self._NextLine()
1602 elif match_field_min:
1603 current_structure.AddLowerBound(
1604 match_field_min.group(1), match_field_min.group(2))
1605 self._NextLine()
1606 elif match_name_plus:
1607 field_name = match_name_plus.group(1)
1608 current_structure.AddField(
1609 field_type, field_name, 'TRUE', False)
1610 self._NextLine()
1611 elif match_name_size_check:
1612 field_name = 'size'
1613 current_structure.AddField(
1614 field_type, field_name, 'FALSE', False)
1615 current_structure.size_check = True
1616 self._NextLine()
1617 else:
1618 print('Invalid field name: %s' % self._line)
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001619 return
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001620 match_type = self._TYPE_RE.search(self._line)
1621 match_return = self._RETURN_RE.search(self._line)
1622 if match_return:
1623 current_structure.error_code = match_return.group(1)
1624 self._NextLine()
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001625 typemap[structure_name] = current_structure
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001626
1627 def _ParseUnions(self, typemap):
1628 """Parses a unions section.
1629
1630 The current line should be _BEGIN_UNIONS and the method will stop parsing
1631 when an _END line is found.
1632
1633 Args:
1634 typemap: A dictionary to which parsed types are added.
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001635 """
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001636 self._NextLine()
1637 while self._END_TOKEN != self._line.rstrip():
1638 match_union = self._UNION_RE.search(self._line)
1639 if not match_union:
1640 print('Invalid structure section, expected _STRUCTURE: %s' % self._line)
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001641 return
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001642 union_name = match_union.group(1)
1643 current_union = Union(union_name)
1644 self._NextLine()
1645 match_type = self._TYPE_RE.search(self._line)
1646 if not match_type:
1647 print('Invalid field type: %s' % self._line)
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001648 return
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001649 while match_type:
1650 field_type = match_type.group(1)
1651 self._NextLine()
1652 match_name = self._NAME_RE.search(self._line)
1653 match_name_array = self._NAME_ARRAY_RE.search(self._line)
1654 if match_name:
1655 field_name = match_name.group(1)
1656 # Field could be interface type with conditional value
1657 current_union.AddField(field_type, field_name, None)
1658 self._NextLine()
1659 elif match_name_array:
1660 field_name = match_name_array.group(1)
1661 array_length = match_name_array.group(2)
1662 current_union.AddField(field_type, field_name, array_length)
1663 self._NextLine()
1664 else:
1665 print('Invalid field name: %s' % self._line)
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001666 return
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001667 match_type = self._TYPE_RE.search(self._line)
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001668 typemap[union_name] = current_union
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001669
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001670def GenerateHeader(typemap):
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001671 """Generates a header file with declarations for all given generator objects.
1672
1673 Args:
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001674 typemap: A dict mapping type names to the corresponding object.
1675 """
1676 out_file = open(_OUTPUT_FILE_H, 'w')
1677 out_file.write(_COPYRIGHT_HEADER)
1678 guard_name = 'TPM2_%s_' % _OUTPUT_FILE_H.upper().replace('.', '_')
1679 out_file.write(_HEADER_FILE_GUARD_HEADER % {'name': guard_name})
1680 out_file.write(_HEADER_FILE_INCLUDES)
1681 # These types are built-in or defined by <stdint.h>; they serve as base cases
1682 # when defining type dependencies.
1683 declared_types = set(_BASIC_TYPES)
1684 # Generate serialize / parse function declarations.
1685 for basic_type in _BASIC_TYPES:
1686 out_file.write(_STANDARD_MARSHAL_DECLARATION % {'type': basic_type})
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001687 for tpm_type in [typemap[x] for x in sorted(typemap.keys())]:
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001688 tpm_type.OutputMarshalDecl(out_file, declared_types, typemap)
1689 out_file.write(_HEADER_FILE_GUARD_FOOTER % {'name': guard_name})
1690 out_file.close()
1691 call(['clang-format', '-i', '-style=Chromium', 'tpm_generated.h'])
1692
1693
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001694def GenerateImplementation(typemap):
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001695 """Generates implementation code for each type.
1696
1697 Args:
1698 types: A list of Typedef objects.
1699 typemap: A dict mapping type names to the corresponding object.
1700 """
1701 out_file = open(_OUTPUT_FILE_CC, 'w')
1702 out_file.write(_COPYRIGHT_HEADER)
1703 out_file.write(_IMPLEMENTATION_FILE_INCLUDES)
1704 marshalled_types = set(_BASIC_TYPES)
1705 for basic_type in _BASIC_TYPES:
1706 out_file.write(_MARSHAL_BASIC_TYPE % {'type': basic_type})
Vadim Bendebury3cd85262015-09-04 17:01:40 -07001707 for tpm_type in [typemap[x] for x in sorted(typemap.keys())]:
ChromeOS Developer9edfbac2015-07-17 16:33:16 -07001708 tpm_type.OutputMarshalImpl(out_file, marshalled_types, typemap)
1709 out_file.close()
1710 call(['clang-format', '-i', '-style=Chromium', 'tpm_generated.c'])