1 # Copyright 2015 The Chromium OS Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 """A code generator for TPM 2.0 structures. 6 7 The structure generator provides classes to create various objects 8 (structures, unions, constants, etc.) and then convert the set of generated 9 objects into valid C files named tpm_generated.{h,c}. 10 11 """ 12 13 from __future__ import print_function 14 15 import datetime 16 import re 17 18 from subprocess import call 19 20 _BASIC_TYPES = ['uint8_t', 'int8_t', 'uint16_t', 'int16_t', 'uint32_t', 21 'int32_t', 'uint64_t', 'int64_t'] 22 _OUTPUT_FILE_H = 'tpm_generated.h' 23 _OUTPUT_FILE_CC = 'tpm_generated.c' 24 COPYRIGHT_HEADER = ( 25 '// Copyright %d The Chromium OS Authors. All rights reserved.\n' 26 '// Use of this source code is governed by a BSD-style license that can ' 27 'be\n' 28 '// found in the LICENSE file.\n' 29 '\n' 30 '// THIS CODE IS GENERATED - DO NOT MODIFY!\n' % 31 datetime.datetime.now().year) 32 HEADER_FILE_GUARD_HEADER = """ 33 #ifndef %(name)s 34 #define %(name)s 35 """ 36 HEADER_FILE_GUARD_FOOTER = """ 37 #endif // %(name)s 38 """ 39 _HEADER_FILE_INCLUDES = """ 40 #include <endian.h> 41 #include <string.h> 42 43 #include "TPM_Types.h" 44 #include "Tpm.h" 45 """ 46 _IMPLEMENTATION_FILE_INCLUDES = """ 47 #include "tpm_generated.h" 48 """ 49 # Function signatures for generated marshaling code are specified in TCG TPM2.0 50 # Library Specification, Part 4: Supporting Routines, sections 4.2.2 and 4.2.3. 51 _MARSHAL_BASIC_TYPE = """ 52 UINT16 %(type)s_Marshal(%(type)s *source, BYTE **buffer, INT32 *size) { 53 %(type)s value_net = *source; 54 if (!size || *size < sizeof(%(type)s)) { 55 return 0; // Nothing has been marshaled. 56 } 57 switch (sizeof(%(type)s)) { 58 case 2: 59 value_net = htobe16(*source); 60 break; 61 case 4: 62 value_net = htobe32(*source); 63 break; 64 case 8: 65 value_net = htobe64(*source); 66 break; 67 default: 68 break; 69 } 70 memcpy(*buffer, &value_net, sizeof(%(type)s)); 71 *buffer += sizeof(%(type)s); 72 *size -= sizeof(%(type)s); 73 return sizeof(%(type)s); 74 } 75 76 TPM_RC %(type)s_Unmarshal(%(type)s *target, BYTE **buffer, INT32 *size) { 77 %(type)s value_net = 0; 78 if (!size || *size < sizeof(%(type)s)) { 79 return TPM_RC_INSUFFICIENT; 80 } 81 memcpy(&value_net, *buffer, sizeof(%(type)s)); 82 switch (sizeof(%(type)s)) { 83 case 2: 84 *target = be16toh(value_net); 85 break; 86 case 4: 87 *target = be32toh(value_net); 88 break; 89 case 8: 90 *target = be64toh(value_net); 91 break; 92 default: 93 *target = value_net; 94 } 95 *buffer += sizeof(%(type)s); 96 *size -= sizeof(%(type)s); 97 return TPM_RC_SUCCESS; 98 } 99 """ 100 _STANDARD_MARSHAL_DECLARATION = """ 101 UINT16 %(type)s_Marshal( 102 %(type)s *source, 103 BYTE **buffer, 104 INT32 *size); 105 106 TPM_RC %(type)s_Unmarshal( 107 %(type)s *target, 108 BYTE **buffer, 109 INT32 *size); 110 """ 111 112 113 def _IsTPM2B(name): 114 return name.startswith('TPM2B_') 115 116 117 class Field(object): 118 """Represents a field in TPM structure or union. 119 120 This object is used in several not fully overlapping cases, not all 121 attributes apply to all use cases. 122 123 The 'array_size' and 'run_time_size' attributes below are related to the 124 following code example: 125 126 struct { 127 int size; 128 byte array[MAX_SIZE] 129 } object. 130 131 In this structure the actual number of bytes in the array could be anything 132 from zero to MAX_SIZE. The field 'size' denotes the actual number of 133 elements at run time. So, when this object is constructed, array_size is 134 'MAX_SIZE' and run_time_size is 'size'. 135 136 The 'selector_value' attribute is used to associate union fields with 137 certain object types. For instance 138 139 typedef union { 140 TPM2B_PUBLIC_KEY_RSA rsa; 141 TPMS_ECC_POINT ecc; 142 } TPMU_PUBLIC_ID; 143 144 the field named 'rsa' will have its 'selector_value' set to 'TPM_ALG_RSA'. 145 146 Attributes: 147 field_type: a string, the type of field. 148 field_name: a string, the name of the field. 149 array_size: a string, see example above 150 run_time_size: a string, see example above 151 selector_value: a string, see example above 152 conditional_value: a string, necessary for validation when unmarshaling. 153 Some types have a value that is allowed for some 154 commands but not others. E.g. 'TPM_RS_PW' is a 155 conditional value for the 'TPMI_SH_AUTH_SESSION' type 156 and TPM_ALG_NULL is a conditional value for the 157 TPMI_ALG_HASH type. 158 """ 159 _MARSHAL_FIELD_ARRAY = """ 160 for (i = 0; i < source->%(array_length)s; ++i) { 161 total_size += %(type)s_Marshal(&source->%(name)s[i], buffer, size); 162 }""" 163 _UNMARSHAL_FIELD_ARRAY = """ 164 for (i = 0; i < target->%(array_length)s; ++i) { 165 result = %(type)s_Unmarshal(&target->%(name)s[i], buffer, size); 166 if (result != TPM_RC_SUCCESS) { 167 return result; 168 } 169 }""" 170 171 def __init__(self, field_type, field_name, 172 selector=None, array_size='', 173 conditional_value='FALSE', 174 run_time_size=None): 175 """Initializes a Field instance. 176 177 Args: 178 field_type: Initial value for the field type attribute. 179 field_name: Initial value for the field name attribute. 180 selector: Initial value for the selector attribute. 181 array_size: Initial value for the array_size attribute. 182 conditional_value: Initial value of the conditional_value attribute. 183 run_time_size: Initial value of the run_time_size attribute 184 """ 185 if not field_type: 186 # Some tables include rows without data type, for instance 'Table 70 - 187 # Definition of TPMU_HA Union' in part 2. These rows are supposed to 188 # cause another case added to the switch in the marshaling function 189 # (processing of TPM_ALG_NULL in this example). Setting field name to '' 190 # makes sure that the actual generated structure/union does not have an 191 # entry for this field, setting type of such field to some value 192 # simplifies functions generating the marshaling code. 193 self.field_type = 'BYTE' 194 self.field_name = '' 195 else: 196 self.field_type = field_type 197 self.field_name = field_name 198 self.array_size = array_size 199 self.selector_value = selector 200 self.conditional_value = conditional_value 201 self.run_time_size = run_time_size 202 203 def OutputMarshal(self, out_file, typemap): 204 """Write a call to marshal the field this instance represents. 205 206 Args: 207 out_file: The output file. 208 typemap: A dict mapping type names to the corresponding object. 209 """ 210 if self.array_size: 211 if self.run_time_size: 212 real_size = self.run_time_size 213 else: 214 real_size = self.array_size 215 out_file.write( 216 self._MARSHAL_FIELD_ARRAY % {'type': self.field_type, 217 'name': self.field_name, 218 'array_length': real_size}) 219 else: 220 typemap[self.field_type].OutputMarshalCall(out_file, self) 221 222 def OutputUnmarshal(self, out_file, typemap): 223 """Write a call to unmarshal the field this instance represents. 224 225 Args: 226 out_file: The output file. 227 typemap: A dict mapping type names to the corresponding object. 228 """ 229 if self.array_size: 230 if self.run_time_size: 231 real_size = self.run_time_size 232 else: 233 real_size = self.array_size 234 out_file.write( 235 self._UNMARSHAL_FIELD_ARRAY % {'type': self.field_type, 236 'name': self.field_name, 237 'array_length': real_size}) 238 else: 239 typemap[self.field_type].OutputUnmarshalCall(out_file, self) 240 241 242 class TPMType(object): 243 """Base type for all TPMTypes. 244 245 Contains functions and string literals common to all TPM types. 246 247 Attributes: 248 _base_type: a string, when set - the very basic type this type is 249 derived from (should be used for marshaling/unmarshaling to 250 shortcut multiple nested invocations). 251 """ 252 # A function to marshal a TPM typedef. 253 _TYPEDEF_MARSHAL_FUNCTION = """ 254 UINT16 %(new_type)s_Marshal( 255 %(new_type)s *source, 256 BYTE **buffer, 257 INT32 *size) { 258 return %(old_type)s_Marshal(source, buffer, size); 259 } 260 """ 261 # The function signature and unmarshaling call to the base type of a TPM 262 # typedef. After the value is unmarshaled, additional validation code is 263 # generated based on tables in TCG TPM2.0 Library Specification, Part 2: 264 # Structures. 265 _TYPEDEF_UNMARSHAL_START = """ 266 TPM_RC %(new_type)s_Unmarshal( 267 %(new_type)s *target, 268 BYTE **buffer, 269 INT32 *size) { 270 TPM_RC result; 271 result = %(old_type)s_Unmarshal(target, buffer, size); 272 if (result != TPM_RC_SUCCESS) { 273 return result; 274 }""" 275 _UNMARSHAL_END = '\n return TPM_RC_SUCCESS;\n}\n' 276 # Snippets of code for value validation. 277 _VALUE_START_SWITCH = '\n switch (%(name)s) {' 278 _VALUE_CASE = '\n case %(value)s:' 279 _VALUE_CASE_IFDEF = '\n#ifdef %(value)s\n case %(value)s:\n#endif' 280 _VALUE_END_SWITCH = """ 281 break; 282 default: 283 return %(error_code)s; 284 }""" 285 # A declaration for marshaling and unmarshaling functions for a TPM type. 286 _MARSHAL_DECLARATION = _STANDARD_MARSHAL_DECLARATION 287 # Snippets of code which make calls to marshaling functions. Marshals a value 288 # of type 'type' into a field 'name' within a structure. This is used in 289 # generation of structure and command marshaling code. 290 _MARSHAL_CALL = """ 291 total_size += %(type)s_Marshal( 292 &source->%(name)s, buffer, size);""" 293 _UNMARSHAL_CALL = """ 294 result = %(type)s_Unmarshal( 295 &target->%(name)s, buffer, size); 296 if (result != TPM_RC_SUCCESS) { 297 return result; 298 }""" 299 300 def __init__(self): 301 self._base_type = None 302 303 def SetBaseType(self, base_type): 304 self._base_type = base_type 305 306 def _GetBaseType(self, out_file, marshalled_types, typemap): 307 '''Return base type for this object. 308 309 The base type is used for shortcutting marshaling/unmarshaling code. 310 311 If _base_type is not set, return the old_type value as the base type. 312 313 If the base type's marshaling/unmarshaling code has not been generated 314 yet, issue it before continuing processing. 315 316 Args: 317 out_file: The output file. 318 marshalled_types: A set of types for which marshal and unmarshal functions 319 have already been generated. 320 typemap: A dict mapping type names to the corresponding object. 321 322 Returns: 323 A string, the name of the type to use for marshaling/unmarshaling. 324 325 ''' 326 if self._base_type: 327 base_type = self._base_type 328 else: 329 base_type = self.old_type 330 if base_type not in marshalled_types: 331 typemap[base_type].OutputMarshalImpl( 332 out_file, marshalled_types, typemap) 333 return base_type 334 335 def HasConditional(self): 336 """Returns true if TPMType has a conditional value.""" 337 return False 338 339 def OutputMarshalCall(self, out_file, field): 340 """Write a call to Marshal function for TPMType to |out_file|. 341 342 Accumulates a variable 'total_size' with the result of marshaling 343 field |field_name| in structure 'source'. 344 345 Args: 346 out_file: The output file. 347 field: A Field object describing this type. 348 """ 349 out_file.write(self._MARSHAL_CALL % {'type': field.field_type, 350 'name': field.field_name}) 351 352 def OutputUnmarshalCall(self, out_file, field): 353 """Write a call to Unmarshal function for TPMType to |out_file|. 354 355 Assigns result of unmarshaling field |field_name| in structure 'source' 356 to variable 'result'. Returns if the unmarshalling was unsuccessful. 357 358 Args: 359 out_file: The output file. 360 field: A Field object describing this type. 361 """ 362 obj_type = field.field_type 363 if obj_type == 'TPM_CC': 364 obj_type = 'UINT32' 365 out_file.write(self._UNMARSHAL_CALL % {'type': obj_type, 366 'name': field.field_name}) 367 368 def _OutputTypedefMarshalDecl(self, out_file, declared_types, typemap): 369 """Write marshal declarations for TPM typedefs to |out_file|. 370 371 Can only be called on Typedef, ConstantType, AttributeStruct, and 372 Interface objects. 373 374 Args: 375 out_file: The output file. 376 declared_types: A set of types for which marshal and unmarshal function 377 declarations have already been generated. 378 typemap: A dict mapping type names to the corresponding object. 379 """ 380 if self.new_type in declared_types: 381 return 382 if self.old_type not in declared_types and self.old_type in typemap: 383 typemap[self.old_type].OutputMarshalDecl( 384 out_file, declared_types, typemap) 385 out_file.write(self._MARSHAL_DECLARATION % {'type': self.new_type}) 386 declared_types.add(self.new_type) 387 388 def _OutputStructOrUnionMarshalDecl(self, out_file, declared_types): 389 """Write marshal declarations for a TPM Structure or Union. 390 391 Can only be called on Structure and Union objects. 392 393 Args: 394 out_file: The output file. 395 declared_types: A set of types for which marshal and unmarshal function 396 declarations have already been generated. 397 """ 398 # TPMU_NAME and TPMU_ENCRYPTED_SECRET type are never used across the 399 # interface. 400 if (self.name in declared_types or 401 self.name == 'TPMU_NAME' or 402 self.name == 'TPMU_ENCRYPTED_SECRET'): 403 return 404 out_file.write(self._MARSHAL_DECLARATION % {'type': self.name}) 405 declared_types.add(self.name) 406 407 408 class Typedef(TPMType): 409 """Represents a TPM typedef. 410 411 Attributes: 412 old_type: The existing type in a typedef statement. 413 new_type: The new type in a typedef statement. 414 """ 415 # A function to unmarshal a TPM typedef with no extra validation. 416 _TYPEDEF_UNMARSHAL_FUNCTION = """ 417 TPM_RC %(new_type)s_Unmarshal( 418 %(new_type)s *target, 419 BYTE **buffer, 420 INT32 *size) { 421 return %(old_type)s_Unmarshal(target, buffer, size); 422 } 423 """ 424 425 def __init__(self, old_type, new_type): 426 """Initializes a Typedef instance. 427 428 Args: 429 old_type: The base type of the attribute structure. 430 new_type: The name of the type. 431 """ 432 super(Typedef, self).__init__() 433 self.old_type = old_type 434 self.new_type = new_type 435 436 def OutputMarshalImpl(self, out_file, marshalled_types, typemap): 437 """Writes marshal implementations for Typedef to |out_file|. 438 439 Args: 440 out_file: The output file. 441 marshalled_types: A set of types for which marshal and unmarshal functions 442 have already been generated. 443 typemap: A dict mapping type names to the corresponding object. 444 """ 445 if self.new_type in marshalled_types: 446 return 447 base_type = self._GetBaseType(out_file, marshalled_types, typemap) 448 out_file.write(self._TYPEDEF_MARSHAL_FUNCTION % {'old_type': base_type, 449 'new_type': self.new_type}) 450 out_file.write( 451 self._TYPEDEF_UNMARSHAL_FUNCTION % {'old_type': base_type, 452 'new_type': self.new_type}) 453 marshalled_types.add(self.new_type) 454 455 def OutputMarshalDecl(self, out_file, declared_types, typemap): 456 """Writes marshal declarations for Typedef to |out_file|. 457 458 Args: 459 out_file: The output file. 460 declared_types: A set of types for which marshal and unmarshal function 461 declarations have already been generated. 462 typemap: A dict mapping type names to the corresponding object. 463 """ 464 self._OutputTypedefMarshalDecl(out_file, declared_types, typemap) 465 466 467 class ConstantType(TPMType): 468 """Represents a TPM Constant type definition. 469 470 Attributes: 471 old_type: The base type of the constant (e.g. 'int'). 472 new_type: The name of the type (e.g. 'TPM_RC'). 473 valid_values: The list of valid values this type can take (e.g. 474 'TPM_RC_SUCCESS'). 475 error_code: Error to be returned when unmarshalling is unsuccessful. 476 """ 477 _CHECK_VALUE = """ 478 if (*target == %(value)s) { 479 return TPM_RC_SUCCESS; 480 }""" 481 _CHECK_VALUE_IFDEF = """ 482 #ifdef %(value)s 483 if (*target == %(value)s) { 484 return TPM_RC_SUCCESS; 485 } 486 #endif""" 487 _UNMARSHAL_END = """ 488 return %(error_code)s; 489 } 490 """ 491 _IFDEF_TYPE_RE = re.compile(r'^TPM_(ALG|CC).*') 492 493 def __init__(self, old_type, new_type): 494 """Initializes a ConstantType instance. 495 496 Values are added to valid_values attribute during parsing. 497 498 Args: 499 old_type: The base type of the constant type. 500 new_type: The name of the type. 501 """ 502 super(ConstantType, self).__init__() 503 self.old_type = old_type 504 self.new_type = new_type 505 self.valid_values = [] 506 self.error_code = 'TPM_RC_VALUE' 507 508 def _NeedsIfdef(self): 509 """Returns True if new_type is a type which needs ifdef enclosing.""" 510 return self._IFDEF_TYPE_RE.search(self.new_type) 511 512 def OutputMarshalImpl(self, out_file, marshalled_types, typemap): 513 """Writes marshal implementations for ConstantType to |out_file|. 514 515 Args: 516 out_file: The output file. 517 marshalled_types: A set of types for which marshal and unmarshal functions 518 have already been generated. 519 typemap: A dict mapping type names to the corresponding object. 520 """ 521 if self.new_type in marshalled_types: 522 return 523 base_type = self._GetBaseType(out_file, marshalled_types, typemap) 524 out_file.write(self._TYPEDEF_MARSHAL_FUNCTION % {'old_type': base_type, 525 'new_type': self.new_type}) 526 out_file.write(self._TYPEDEF_UNMARSHAL_START % {'old_type': base_type, 527 'new_type': self.new_type}) 528 for value in self.valid_values: 529 if self._NeedsIfdef(): 530 out_file.write(self._CHECK_VALUE_IFDEF % {'value': value}) 531 else: 532 out_file.write(self._CHECK_VALUE % {'value': value}) 533 out_file.write(self._UNMARSHAL_END % {'error_code': self.error_code}) 534 marshalled_types.add(self.new_type) 535 536 def OutputMarshalDecl(self, out_file, declared_types, typemap): 537 """Writes marshal declarations for ConstantType to |out_file|. 538 539 Args: 540 out_file: The output file. 541 declared_types: A set of types for which marshal and unmarshal function 542 declarations have already been generated. 543 typemap: A dict mapping type names to the corresponding object. 544 """ 545 self._OutputTypedefMarshalDecl(out_file, declared_types, typemap) 546 547 548 class AttributeStructure(TPMType): 549 """Represents a TPM attribute structure type definition. 550 551 Attributes: 552 old_type: The base type of the constant (e.g. 'int'). 553 new_type: The name of the type (e.g. 'TPMA_OBJECT'). 554 reserved: The list of bit bounds where bits must be 0 (e.g. ['10_2','3']). 555 """ 556 # Attribute structures need an explicit cast to the base type. 557 _ATTRIBUTE_MARSHAL_FUNCTION = """ 558 UINT16 %(new_type)s_Marshal( 559 %(new_type)s *source, 560 BYTE **buffer, 561 INT32 *size) { 562 return %(old_type)s_Marshal((%(old_type)s*)source, buffer, size); 563 } 564 """ 565 _ATTRIBUTE_UNMARSHAL_START = """ 566 TPM_RC %(new_type)s_Unmarshal( 567 %(new_type)s *target, 568 BYTE **buffer, 569 INT32 *size) { 570 TPM_RC result; 571 result = %(old_type)s_Unmarshal((%(old_type)s*)target, buffer, size); 572 if (result != TPM_RC_SUCCESS) { 573 return result; 574 }""" 575 _CHECK_RESERVED = """ 576 if (target->reserved%(bits)s != 0) { 577 return TPM_RC_RESERVED_BITS; 578 }""" 579 580 def __init__(self, old_type, new_type): 581 """Initializes an AttributeStructure instance. 582 583 Values may be added to reserved attribute during parsing. 584 585 Args: 586 old_type: The base type of the attribute structure. 587 new_type: The name of the type. 588 """ 589 super(AttributeStructure, self).__init__() 590 self.old_type = old_type 591 self.new_type = new_type 592 self.reserved = [] 593 594 def OutputMarshalImpl(self, out_file, marshalled_types, typemap): 595 """Writes marshal implementations for AttributStructure to |out_file|. 596 597 Args: 598 out_file: The output file. 599 marshalled_types: A set of types for which marshal and unmarshal functions 600 have already been generated. 601 typemap: A dict mapping type names to the corresponding object. 602 """ 603 if self.new_type in marshalled_types: 604 return 605 base_type = self._GetBaseType(out_file, marshalled_types, typemap) 606 out_file.write(self._ATTRIBUTE_MARSHAL_FUNCTION % 607 {'old_type': base_type, 608 'new_type': self.new_type}) 609 out_file.write(self._ATTRIBUTE_UNMARSHAL_START % 610 {'old_type': base_type, 611 'new_type': self.new_type}) 612 for bits in self.reserved: 613 out_file.write(self._CHECK_RESERVED % {'bits': bits}) 614 out_file.write(self._UNMARSHAL_END) 615 marshalled_types.add(self.new_type) 616 617 def OutputMarshalDecl(self, out_file, declared_types, typemap): 618 """Writes marshal declarations for AttributeStructure to |out_file|. 619 620 Args: 621 out_file: The output file. 622 declared_types: A set of types for which marshal and unmarshal function 623 declarations have already been generated. 624 typemap: A dict mapping type names to the corresponding object. 625 """ 626 self._OutputTypedefMarshalDecl(out_file, declared_types, typemap) 627 628 629 class Interface(TPMType): 630 """Represents a TPM interface type definition. 631 632 Attributes: 633 old_type: The base type of the interface (e.g. 'TPM_HANDLE'). 634 new_type: The name of the type (e.g. 'TPMI_DH_OBJECT'). 635 valid_values: List of valid values for new_type. If this is not empty, 636 valid values for new_type is explicitly defined in the spec. 637 bounds: List of pairs representing bounds. If nonempty, target must fall 638 between one of these bounds. 639 conditional_value: Name of conditionally allowed value. If there is no 640 such value, this variable will be None. 641 supported_values: String literal indicating the name of a list of supported 642 values to be substituted at compile time (e.g. 'AES_KEY_SIZES_BITS'). 643 If this is not None, valid values for new_type depends on the 644 implementation. 645 error_code: Return code when an unmarshalling error occurs. 646 """ 647 _INTERFACE_CONDITIONAL_UNMARSHAL_START = """ 648 TPM_RC %(new_type)s_Unmarshal( 649 %(new_type)s *target, 650 BYTE **buffer, 651 INT32 *size, 652 BOOL allow_conditional_value) { 653 TPM_RC result;""" 654 _INTERFACE_UNMARSHAL_START = """ 655 TPM_RC %(new_type)s_Unmarshal( 656 %(new_type)s *target, 657 BYTE **buffer, 658 INT32 *size) { 659 TPM_RC result;""" 660 _UNMARSHAL_VALUE = """ 661 result = %(old_type)s_Unmarshal(target, buffer, size); 662 if (result != TPM_RC_SUCCESS) { 663 return result; 664 }""" 665 _UNMARSHAL_VALUE_ALLOW_RC_VALUE = """ 666 result = %(old_type)s_Unmarshal(target, buffer, size); 667 if ((result != TPM_RC_VALUE) && (result != TPM_RC_SUCCESS)) { 668 return result; 669 }""" 670 _SETUP_CHECK_SUPPORTED_VALUES = """ 671 uint16_t supported_values[] = %(supported_values)s; 672 size_t length = sizeof(supported_values)/sizeof(supported_values[0]); 673 size_t i; 674 BOOL is_supported_value = FALSE;""" 675 _CHECK_SUPPORTED_VALUES = """ 676 for (i = 0; i < length; ++i) { 677 if (*target == supported_values[i]) { 678 is_supported_value = TRUE; 679 break; 680 } 681 } 682 if (!is_supported_value) { 683 return %(error_code)s; 684 }""" 685 _CHECK_CONDITIONAL = """ 686 if (*target == %(name)s) { 687 return allow_conditional_value ? TPM_RC_SUCCESS : %(error_code)s; 688 }""" 689 _SETUP_CHECK_VALUES = '\n BOOL has_valid_value = FALSE;' 690 _VALUE_END_SWITCH = """ 691 has_valid_value = TRUE; 692 break; 693 }""" 694 _CHECK_BOUND = """ 695 if((*target >= %(lower)s) && (*target <= %(upper)s)) { 696 has_valid_value = TRUE; 697 }""" 698 _CHECK_VALUES_END = """ 699 if (!has_valid_value) { 700 return %(error_code)s; 701 }""" 702 _CONDITIONAL_MARSHAL_DECLARATION = """ 703 UINT16 %(type)s_Marshal( 704 %(type)s *source, 705 BYTE **buffer, 706 INT32 *size); 707 708 TPM_RC %(type)s_Unmarshal( 709 %(type)s *target, 710 BYTE **buffer, 711 INT32 *size, 712 BOOL allow_conditioanl_value); 713 """ 714 _CONDITIONAL_UNMARSHAL_CALL = """ 715 result = %(type)s_Unmarshal( 716 &target->%(name)s, buffer, size, %(flag)s); 717 if (result != TPM_RC_SUCCESS) { 718 return result; 719 }""" 720 _IFDEF_TYPE_RE = re.compile(r'^TPMI_(ALG|ECC)_.*') 721 722 def __init__(self, old_type, new_type): 723 """Initializes an Interface instance. 724 725 Values may be added/assigned to valid_values, bounds, conditional_value, 726 supported_values, and error_code attributes new values during parsing. 727 728 Args: 729 old_type: The base type of the interface. 730 new_type: The name of the type. 731 """ 732 super(Interface, self).__init__() 733 self.old_type = old_type 734 self.new_type = new_type 735 self.valid_values = [] 736 self.bounds = [] 737 self.conditional_value = None 738 self.supported_values = None 739 self.error_code = 'TPM_RC_VALUE' 740 741 def HasConditional(self): 742 """Returns true if Interface has a valid conditional_value.""" 743 return self.conditional_value is not None 744 745 def _NeedsIfdef(self): 746 """Returns True if new_type is a type which needs ifdef enclosing.""" 747 return self._IFDEF_TYPE_RE.search(self.new_type) 748 749 def OutputMarshalImpl(self, out_file, marshalled_types, typemap): 750 """Writes marshal implementation for Interface to |out_file|. 751 752 Args: 753 out_file: The output file. 754 marshalled_types: A set of types for which marshal and unmarshal functions 755 have already been generated. 756 typemap: A dict mapping type names to the corresponding object. 757 """ 758 if self.new_type in marshalled_types: 759 return 760 base_type = self._GetBaseType(out_file, marshalled_types, typemap) 761 out_file.write(self._TYPEDEF_MARSHAL_FUNCTION % {'old_type': base_type, 762 'new_type': self.new_type}) 763 if self.conditional_value: 764 out_file.write(self._INTERFACE_CONDITIONAL_UNMARSHAL_START % 765 {'old_type': base_type, 766 'new_type': self.new_type}) 767 else: 768 out_file.write( 769 self._INTERFACE_UNMARSHAL_START % {'old_type': base_type, 770 'new_type': self.new_type}) 771 # Creating necessary local variables. 772 if self.supported_values: 773 out_file.write(self._SETUP_CHECK_SUPPORTED_VALUES % 774 {'supported_values': self.supported_values}) 775 if len(self.valid_values)+len(self.bounds) > 0: 776 out_file.write(self._SETUP_CHECK_VALUES) 777 out_file.write(self._UNMARSHAL_VALUE_ALLOW_RC_VALUE % 778 {'old_type': base_type}) 779 else: 780 out_file.write(self._UNMARSHAL_VALUE % {'old_type': base_type}) 781 782 if self.supported_values: 783 out_file.write(self._CHECK_SUPPORTED_VALUES % 784 {'supported_values': self.supported_values, 785 'error_code': self.error_code}) 786 if self.conditional_value: 787 out_file.write( 788 self._CHECK_CONDITIONAL % {'name': self.conditional_value, 789 'error_code': self.error_code}) 790 # Checking for valid values. 791 if len(self.valid_values)+len(self.bounds) > 0: 792 if self.valid_values: 793 out_file.write(self._VALUE_START_SWITCH % {'name': '*target'}) 794 for value in self.valid_values: 795 if self._NeedsIfdef(): 796 out_file.write(self._VALUE_CASE_IFDEF % {'value': value}) 797 else: 798 out_file.write(self._VALUE_CASE % {'value': value}) 799 out_file.write(self._VALUE_END_SWITCH) 800 for (lower, upper) in self.bounds: 801 out_file.write( 802 self._CHECK_BOUND % {'lower': lower, 'upper': upper}) 803 out_file.write(self._CHECK_VALUES_END % {'error_code': self.error_code}) 804 805 out_file.write(self._UNMARSHAL_END) 806 marshalled_types.add(self.new_type) 807 808 def OutputMarshalDecl(self, out_file, declared_types, typemap): 809 """Writes marshal declarations for Interface to |out_file|. 810 811 Outputted declaration depends on whether Interface type has a 812 conditionally valid value. 813 814 Args: 815 out_file: The output file. 816 declared_types: A set of types for which marshal and unmarshal function 817 declarations have already been generated. 818 typemap: A dict mapping type names to the corresponding object. 819 """ 820 if self.new_type in declared_types: 821 return 822 if self.old_type not in declared_types: 823 typemap[self.old_type].OutputMarshalDecl( 824 out_file, declared_types, typemap) 825 if self.HasConditional(): 826 out_file.write( 827 self._CONDITIONAL_MARSHAL_DECLARATION % {'type': self.new_type}) 828 else: 829 out_file.write(self._MARSHAL_DECLARATION % {'type': self.new_type}) 830 declared_types.add(self.new_type) 831 832 def OutputUnmarshalCall( 833 self, out_file, field): 834 """Write a call to Unmarshal function for Interface type to |out_file|. 835 836 Override TPMType OutputUnmarshalCall because when an Interface type has 837 a conditionally valid value, a BOOL value (|conditional_valid|) is passed 838 as a parameter. 839 840 Args: 841 out_file: The output file. 842 field: A Field object representing an element of this interface. 843 """ 844 if self.conditional_value: 845 out_file.write( 846 self._CONDITIONAL_UNMARSHAL_CALL % {'type': field.field_type, 847 'name': field.field_name, 848 'flag': field.conditional_value}) 849 else: 850 out_file.write(self._UNMARSHAL_CALL % {'type': field.field_type, 851 'name': field.field_name}) 852 853 854 class Structure(TPMType): 855 """Represents a TPM structure. 856 857 Attributes: 858 name: The name of the structure. 859 fields: A list of Field objects representing struct fields. 860 upper_bounds: A dictionary of (name, val) tuples mapping name to max val. 861 lower_bounds: A dictionary of (name, val) tuples mapping name to min val. 862 size_check: Set if TPM2B structure must be size checked (triggered by size=) 863 valid_tag_values: A list of values field tag is allowed to take. 864 error_code: The return code to be returned if an error occurs 865 """ 866 _STRUCTURE_MARSHAL_START = """ 867 UINT16 %(name)s_Marshal( 868 %(name)s *source, 869 BYTE **buffer, 870 INT32 *size) { 871 UINT16 total_size = 0;""" 872 _STRUCTURE_UNMARSHAL_START = """ 873 TPM_RC %(name)s_Unmarshal( 874 %(name)s *target, 875 BYTE **buffer, 876 INT32 *size) { 877 TPM_RC result;""" 878 _MARSHAL_END = '\n return total_size;\n}\n' 879 _SETUP_ARRAY_FIELD = '\n INT32 i;' 880 _CHECK_SIZE_START = """ 881 UINT32 start_size = *size; 882 UINT32 struct_size;""" 883 _CHECK_SIZE_END = """ 884 struct_size = start_size - *size - sizeof(target->t.size); 885 if (struct_size != target->t.size) { 886 return TPM_RC_SIZE; 887 }""" 888 _TPM2B_ZERO_SIZE = """ 889 if (target->t.size == 0) { 890 return %(return_value)s; 891 }""" 892 _CHECK_BOUND = """ 893 if (target->%(name)s %(operator)s %(bound_value)s) { 894 return %(error_code)s; 895 }""" 896 _FIX_SIZE_FIELD = """ 897 { 898 BYTE *size_location = *buffer - total_size; 899 INT32 size_field_size = sizeof(%(size_field_type)s); 900 UINT16 payload_size = total_size - (UINT16)size_field_size; 901 %(size_field_type)s_Marshal(&payload_size, 902 &size_location, &size_field_size); 903 }""" 904 905 def __init__(self, name): 906 """Initializes a Structure instance. 907 908 Initially the instance will have no fields, upper_bounds, lower_bounds, or 909 valid_tag_values. Those can be added with AddField(), AddUpperBound(), 910 AddLowerBound(), and AddTagVal() methods. 911 912 Args: 913 name: The name of the structure. 914 """ 915 super(Structure, self).__init__() 916 self.name = name 917 self.fields = [] 918 self.upper_bounds = {} 919 self.lower_bounds = {} 920 self.size_check = False 921 self.valid_tag_values = [] 922 self.error_code = 'TPM_RC_VALUE' 923 924 def AddField(self, field): 925 """Adds a field to fields attribute in Structure. 926 927 Args: 928 field: Instance of Field 929 """ 930 self.fields.append(field) 931 932 def AddUpperBound(self, field_name, value): 933 """Adds an upper bound for a field. 934 935 Args: 936 field_name: Name of field with bound. 937 value: Value of upper bound. 938 """ 939 if _IsTPM2B(self.name): 940 field_name = 't.' + field_name 941 self.upper_bounds[field_name] = value 942 943 def AddLowerBound(self, field_name, value): 944 """Adds a lower bound for a field. 945 946 Args: 947 field_name: Name of field with bound. 948 value: Value of lower bound. 949 """ 950 if _IsTPM2B(self.name): 951 field_name = 't.' + field_name 952 self.lower_bounds[field_name] = value 953 954 def _AddTagValue(self, value): 955 """Adds a valid value for tag field. 956 957 Args: 958 value: Valid value for tag field. 959 """ 960 self.valid_tag_values.append(value) 961 962 def _GetFieldTypes(self): 963 """Creates a set which holds all current field types. 964 965 Returns: 966 A set of field types. 967 """ 968 return set([field.field_type for field in self.fields]) 969 970 def OutputMarshalImpl(self, out_file, marshalled_types, typemap): 971 """Writes marshal implementations for Structure to |out_file|. 972 973 Args: 974 out_file: The output file. 975 marshalled_types: A set of types for which marshal and unmarshal functions 976 have already been generated. 977 typemap: A dict mapping type names to the corresponding object. 978 """ 979 if self.name in marshalled_types: 980 return 981 982 # Make sure any dependencies already have marshal functions defined. 983 for field_type in self._GetFieldTypes(): 984 if field_type not in marshalled_types: 985 typemap[field_type].OutputMarshalImpl( 986 out_file, marshalled_types, typemap) 987 marshalled_types.add(field_type) 988 989 out_file.write(self._STRUCTURE_MARSHAL_START % {'name': self.name}) 990 # If any field is an array, create local variable INT32 i. 991 for field in self.fields: 992 if field.array_size: 993 out_file.write(self._SETUP_ARRAY_FIELD) 994 break 995 for field in self.fields: 996 # Each TPM2B is a union of two sized buffers, one which is type specific 997 # (the 't' element) and the other is a generic value (the 'b' element). 998 # For this reason a 't.' is prepended for fields in a TPM2B type. See 999 # section 9.11.6 in TCG TPM2.0 Library Specification, Part 2: Structures 1000 # for more details. 1001 if _IsTPM2B(self.name): 1002 field.field_name = 't.' + field.field_name 1003 if field.run_time_size: 1004 field.run_time_size = 't.' + field.run_time_size 1005 field.OutputMarshal(out_file, typemap) 1006 if self.size_check: 1007 out_file.write(self._FIX_SIZE_FIELD % {'size_field_type': self.fields[0].field_type}) 1008 out_file.write(self._MARSHAL_END) 1009 1010 out_file.write(self._STRUCTURE_UNMARSHAL_START % {'name': self.name}) 1011 if self.size_check: 1012 out_file.write(self._CHECK_SIZE_START) 1013 # If any field is an array, create local variable INT32 i. 1014 for field in self.fields: 1015 if field.array_size: 1016 out_file.write(self._SETUP_ARRAY_FIELD) 1017 break 1018 for field in self.fields: 1019 field.OutputUnmarshal(out_file, typemap) 1020 return_value = self.error_code 1021 if field.field_name == 't.size' and self.size_check: 1022 out_file.write(self._TPM2B_ZERO_SIZE % {'return_value': 'TPM_RC_SIZE'}) 1023 if field.field_name == 't.size' and not self.size_check: 1024 out_file.write( 1025 self._TPM2B_ZERO_SIZE % {'return_value': 'TPM_RC_SUCCESS'}) 1026 if field.field_name in self.upper_bounds: 1027 if (field.field_name == 'count' or 1028 field.field_name == 't.size' or 1029 field.field_name == 'size'): 1030 return_value = 'TPM_RC_SIZE' 1031 out_file.write(self._CHECK_BOUND % 1032 {'name': field.field_name, 1033 'operator': '>', 1034 'bound_value': self.upper_bounds[field.field_name], 1035 'error_code': return_value}) 1036 if field.field_name in self.lower_bounds: 1037 if (field.field_name == 'count' or 1038 field.field_name == 't.size' or 1039 field.field_name == 'size'): 1040 return_value = 'TPM_RC_SIZE' 1041 out_file.write(self._CHECK_BOUND % 1042 {'name': field.field_name, 1043 'operator': '<', 1044 'bound_value': self.lower_bounds[field.field_name], 1045 'error_code': return_value}) 1046 if field.field_name == 'tag' and self.valid_tag_values: 1047 out_file.write(self._VALUE_START_SWITCH % {'name': 'target->tag'}) 1048 for value in self.valid_tag_values: 1049 out_file.write(self._VALUE_CASE % {'value': value}) 1050 out_file.write(self._VALUE_END_SWITCH % {'error_code': 'TPM_RC_TAG'}) 1051 if self.size_check: 1052 out_file.write(self._CHECK_SIZE_END) 1053 if not self.fields: 1054 # The spec includes a definition of an empty structure, as a side effect 1055 # the marshaling/unmarshaling functions become empty, the compiler 1056 # warning is suppressed by the below statement. 1057 out_file.write(' (void)result;\n') 1058 out_file.write(self._UNMARSHAL_END) 1059 1060 marshalled_types.add(self.name) 1061 1062 def OutputMarshalDecl(self, out_file, declared_types, _): 1063 """Writes marshal declarations for Structure to |out_file|. 1064 1065 Args: 1066 out_file: The output file. 1067 declared_types: A set of types for which marshal and unmarshal function 1068 declarations have already been generated. 1069 """ 1070 self._OutputStructOrUnionMarshalDecl(out_file, declared_types) 1071 1072 1073 class Union(TPMType): 1074 """Represents a TPM union. 1075 1076 Attributes: 1077 name: The name of the union. 1078 fields: A list of Field objects representing union fields. 1079 """ 1080 1081 _UNION_MARSHAL_START = """ 1082 UINT16 %(name)s_Marshal( 1083 %(name)s *source, 1084 BYTE **buffer, 1085 INT32 *size, 1086 UINT32 selector) { 1087 %(array_extras)s 1088 switch(selector) {""" 1089 _UNION_UNMARSHAL_START = """ 1090 TPM_RC %(name)s_Unmarshal( 1091 %(name)s *target, 1092 BYTE **buffer, 1093 INT32 *size, 1094 UINT32 selector) { 1095 switch(selector) {""" 1096 _MARSHAL_END = '\n }\n return 0;\n}\n' 1097 _UNMARSHAL_END = '\n }\n return TPM_RC_SELECTOR;\n}\n' 1098 _MARSHAL_DECLARATION = """ 1099 UINT16 %(type)s_Marshal( 1100 %(type)s *source, 1101 BYTE **buffer, 1102 INT32 *size, 1103 UINT32 selector); 1104 1105 TPM_RC %(type)s_Unmarshal( 1106 %(type)s *target, 1107 BYTE **buffer, 1108 INT32 *size, 1109 UINT32 selector); 1110 """ 1111 _CASE_SELECTOR = """ 1112 case %(selector)s:""" 1113 _MARSHAL_EMPTY = """ 1114 return 0;""" 1115 _UNMARSHAL_EMPTY = """ 1116 return TPM_RC_SUCCESS;""" 1117 _MARSHAL_FIELD = """ 1118 return %(type)s_Marshal( 1119 (%(type)s*)&source->%(name)s, buffer, size);""" 1120 _UNMARSHAL_FIELD = """ 1121 return %(type)s_Unmarshal( 1122 (%(type)s*)&target->%(name)s, buffer, size);""" 1123 _SETUP_MARSHAL_FIELD_ARRAY = """ 1124 INT32 i; 1125 UINT16 total_size = 0;""" 1126 _SETUP_UNMARSHAL_FIELD_ARRAY = """ 1127 INT32 i; 1128 TPM_RC result = TPM_RC_SUCCESS;""" 1129 _MARSHAL_FIELD_ARRAY = """ 1130 for (i = 0; i < %(array_length)s; ++i) { 1131 total_size += %(type)s_Marshal( 1132 &source->%(name)s[i], buffer, size); 1133 } 1134 return total_size;""" 1135 _UNMARSHAL_FIELD_ARRAY = """ 1136 for (i = 0; i < %(array_length)s; ++i) { 1137 result = %(type)s_Unmarshal( 1138 &target->%(name)s[i], buffer, size); 1139 if (result != TPM_RC_SUCCESS) { 1140 return result; 1141 } 1142 } 1143 return TPM_RC_SUCCESS;""" 1144 _UNMARSHAL_FIELD_CONDITIONAL = """ 1145 return %(type)s_Unmarshal( 1146 &target->%(name)s, buffer, size, FALSE);""" 1147 _UNION_MARSHAL_CALL = """ 1148 total_size += %(type)s_Marshal( 1149 &source->%(name)s, buffer, size, source->%(selector)s);""" 1150 _UNION_UNMARSHAL_CALL = """ 1151 result = %(type)s_Unmarshal( 1152 &target->%(name)s, buffer, size, target->%(selector)s); 1153 if (result != TPM_RC_SUCCESS) { 1154 return result; 1155 }""" 1156 _IFDEF = '\n#ifdef %(type)s' 1157 _ENDIF = '\n#endif' 1158 _IFDEF_TYPE_RE = re.compile(r'^TPM_(ALG|CC).*') 1159 1160 def __init__(self, name): 1161 """Initializes a Union instance. 1162 1163 Initially the instance will have no fields. Fields are added with the 1164 AddField() method. 1165 1166 Args: 1167 name: The name of the structure. 1168 """ 1169 super(Union, self).__init__() 1170 self.name = name 1171 self.fields = [] 1172 1173 def _NeedsIfdef(self, selector): 1174 """Returns True if selector is a type which needs ifdef enclosing.""" 1175 return self._IFDEF_TYPE_RE.search(selector) 1176 1177 def AddField(self, field): 1178 """Adds a field to fields attribute in Union. 1179 1180 Args: 1181 field: instance of Field 1182 """ 1183 # xor is a C++ keyword and must be fixed. 1184 if field.field_name == 'xor': 1185 field.field_name = 'xor_' 1186 self.fields.append(field) 1187 1188 def _OutputMarshalField( 1189 self, out_file, field_type, field_name, array_length): 1190 """Write a call to marshal a field in this union. 1191 1192 Args: 1193 out_file: The output file. 1194 field_type: The type of field. 1195 field_name: The name of the field. 1196 array_length: Variable indicating length of array, None if field is not 1197 an array. 1198 """ 1199 if array_length: 1200 out_file.write(self._MARSHAL_FIELD_ARRAY % {'type': field_type, 1201 'name': field_name, 1202 'array_length': array_length}) 1203 else: 1204 out_file.write(self._MARSHAL_FIELD % {'type': field_type, 1205 'name': field_name}) 1206 1207 def _OutputUnmarshalField( 1208 self, out_file, field_type, field_name, array_length, typemap): 1209 """Write a call to unmarshal a field in this union. 1210 1211 Args: 1212 out_file: The output file object. 1213 field_type: The type of field. 1214 field_name: The name of the field. 1215 array_length: Variable indicating length of array, None if field is not 1216 an array. 1217 typemap: A dict mapping type names to the corresponding object. 1218 """ 1219 if array_length: 1220 out_file.write( 1221 self._UNMARSHAL_FIELD_ARRAY % {'type': field_type, 1222 'name': field_name, 1223 'array_length': array_length}) 1224 elif typemap[field_type].HasConditional(): 1225 out_file.write( 1226 self._UNMARSHAL_FIELD_CONDITIONAL % {'type': field_type, 1227 'name': field_name}) 1228 else: 1229 out_file.write(self._UNMARSHAL_FIELD % {'type': field_type, 1230 'name': field_name}) 1231 1232 def OutputMarshalImpl(self, out_file, marshalled_types, typemap): 1233 """Writes marshal implementations for Union to |out_file|. 1234 1235 Args: 1236 out_file: The output file. 1237 marshalled_types: A set of types for which marshal and unmarshal functions 1238 have already been generated. 1239 typemap: A dict mapping type names to the corresponding object. 1240 """ 1241 if (self.name in marshalled_types or 1242 self.name == 'TPMU_NAME' or 1243 self.name == 'TPMU_ENCRYPTED_SECRET' or 1244 not self.fields): 1245 return 1246 1247 field_types = {f.field_name: f.field_type for f in self.fields} 1248 array_lengths = {} 1249 for f in self.fields: 1250 if f.array_size: 1251 array_lengths[f.field_name] = f.array_size 1252 else: 1253 array_lengths[f.field_name] = None 1254 1255 # Make sure any dependencies already have marshal functions defined. 1256 for field_type in field_types.itervalues(): 1257 if field_type not in marshalled_types: 1258 typemap[field_type].OutputMarshalImpl( 1259 out_file, marshalled_types, typemap) 1260 marshalled_types.add(field_type) 1261 if self.fields[0].array_size: 1262 array_extras = self._SETUP_MARSHAL_FIELD_ARRAY 1263 else: 1264 array_extras = '' 1265 out_file.write(self._UNION_MARSHAL_START % {'name': self.name, 1266 'array_extras': array_extras}) 1267 # Set up variables if Union is an array type. 1268 for field in self.fields: 1269 selector = field.selector_value 1270 if not selector: 1271 continue 1272 field_name = field.field_name 1273 if self._NeedsIfdef(selector): 1274 out_file.write(self._IFDEF % {'type': selector}) 1275 out_file.write(self._CASE_SELECTOR % {'selector': selector}) 1276 # Selector is not associated with a name, so no marshaling occurs. 1277 if not field_name: 1278 out_file.write(self._MARSHAL_EMPTY) 1279 if self._NeedsIfdef(selector): 1280 out_file.write(self._ENDIF) 1281 continue 1282 field_type = field_types[field_name] 1283 array_length = array_lengths[field_name] 1284 self._OutputMarshalField(out_file, field_type, field_name, array_length) 1285 if self._NeedsIfdef(selector): 1286 out_file.write(self._ENDIF) 1287 out_file.write(self._MARSHAL_END) 1288 out_file.write(self._UNION_UNMARSHAL_START % {'name': self.name}) 1289 # Set up variables if Union is an array type. 1290 if self.fields[0].array_size: 1291 out_file.write(self._SETUP_UNMARSHAL_FIELD_ARRAY) 1292 for field in self.fields: 1293 selector = field.selector_value 1294 if not selector: 1295 continue 1296 field_name = field.field_name 1297 if self._NeedsIfdef(selector): 1298 out_file.write(self._IFDEF % {'type': selector}) 1299 out_file.write(self._CASE_SELECTOR % {'selector': selector}) 1300 # Selector is not associated with a name, so no unmarshaling occurs. 1301 if not field_name: 1302 out_file.write(self._UNMARSHAL_EMPTY) 1303 if self._NeedsIfdef(selector): 1304 out_file.write(self._ENDIF) 1305 continue 1306 field_type = field_types[field_name] 1307 array_length = array_lengths[field_name] 1308 self._OutputUnmarshalField( 1309 out_file, field_type, field_name, array_length, typemap) 1310 if self._NeedsIfdef(selector): 1311 out_file.write(self._ENDIF) 1312 out_file.write(self._UNMARSHAL_END) 1313 marshalled_types.add(self.name) 1314 1315 def OutputMarshalDecl(self, out_file, declared_types, _): 1316 """Writes marshal declarations for Union to |out_file|. 1317 1318 Args: 1319 out_file: The output file. 1320 declared_types: A set of types for which marshal and unmarshal function 1321 declarations have already been generated. 1322 """ 1323 self._OutputStructOrUnionMarshalDecl(out_file, declared_types) 1324 1325 def OutputMarshalCall(self, out_file, field): 1326 """Write a call to marshal function for Union type to |out_file|. 1327 1328 Override TPMType OutputMarshalCall to pass in selector value. 1329 1330 Args: 1331 out_file: The output file. 1332 field: A Field object representing a member of this union 1333 """ 1334 out_file.write(self._UNION_MARSHAL_CALL % 1335 {'type': field.field_type, 1336 'name': field.field_name, 1337 'selector': field.selector_value}) 1338 1339 def OutputUnmarshalCall(self, out_file, field): 1340 """Write a call to unmarshal function for Union type to |out_file|. 1341 1342 Override TPMType OutputUnmashalCall to pass in selector value. 1343 1344 Args: 1345 out_file: The output file. 1346 field: A Field object representing a member of this union 1347 """ 1348 out_file.write(self._UNION_UNMARSHAL_CALL % 1349 {'type': field.field_type, 1350 'name': field.field_name, 1351 'selector': field.selector_value}) 1352 1353 1354 def GenerateHeader(typemap): 1355 """Generates a header file with declarations for all given generator objects. 1356 1357 Args: 1358 typemap: A dict mapping type names to the corresponding object. 1359 """ 1360 out_file = open(_OUTPUT_FILE_H, 'w') 1361 out_file.write(COPYRIGHT_HEADER) 1362 guard_name = 'TPM2_%s_' % _OUTPUT_FILE_H.upper().replace('.', '_') 1363 out_file.write(HEADER_FILE_GUARD_HEADER % {'name': guard_name}) 1364 out_file.write(_HEADER_FILE_INCLUDES) 1365 # These types are built-in or defined by <stdint.h>; they serve as base cases 1366 # when defining type dependencies. 1367 declared_types = set(_BASIC_TYPES) 1368 # Generate serialize / parse function declarations. 1369 for basic_type in _BASIC_TYPES: 1370 out_file.write(_STANDARD_MARSHAL_DECLARATION % {'type': basic_type}) 1371 for tpm_type in [typemap[x] for x in sorted(typemap.keys())]: 1372 tpm_type.OutputMarshalDecl(out_file, declared_types, typemap) 1373 out_file.write(HEADER_FILE_GUARD_FOOTER % {'name': guard_name}) 1374 out_file.close() 1375 call(['clang-format', '-i', '-style=Chromium', 'tpm_generated.h']) 1376 1377 1378 def GenerateImplementation(typemap): 1379 """Generates implementation code for each type. 1380 1381 Args: 1382 typemap: A dict mapping string type names to the corresponding object. 1383 """ 1384 out_file = open(_OUTPUT_FILE_CC, 'w') 1385 out_file.write(COPYRIGHT_HEADER) 1386 out_file.write(_IMPLEMENTATION_FILE_INCLUDES) 1387 marshalled_types = set(_BASIC_TYPES) 1388 for basic_type in _BASIC_TYPES: 1389 out_file.write(_MARSHAL_BASIC_TYPE % {'type': basic_type}) 1390 for tpm_type in [typemap[x] for x in sorted(typemap.keys())]: 1391 tpm_type.OutputMarshalImpl(out_file, marshalled_types, typemap) 1392 out_file.close() 1393 call(['clang-format', '-i', '-style=Chromium', 'tpm_generated.c']) 1394