| #!/usr/bin/python |
| |
| # Copyright 2015 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """A Main file for command and structure generators. |
| |
| Takes in structures.txt and commands.txt as outputted by extract_*.sh, then |
| passes files as input to structure_generator and command_generator objects. |
| """ |
| |
| from __future__ import print_function |
| |
| import os |
| import re |
| import subprocess |
| import sys |
| |
| import command_generator |
| import extract_structures |
| import structure_generator |
| |
| TMP_DIR = '/tmp' |
| TYPES_FILE = 'tpm_types.h' |
| |
| |
| class GeneratorException(Exception): |
| """Generator error, a convenience class.""" |
| pass |
| |
| usage = (''' |
| usage: %s [-h|[tar_archive|part2.html part3.html]] |
| |
| -h show this message and exit |
| |
| tar_archive - a tarred archive consisting of at least two HTML files, |
| parts 2 and 3 of the TCG TPM2 library specification. File |
| names must include 'part2' and 'part3'. The extracted files |
| could be found in %s after this script finished processing. |
| |
| part{23}.html - parts 2 and 3 of the TCG TPM2 library specification in |
| html format. |
| ''' % (os.path.basename(__file__), TMP_DIR)) |
| |
| |
| def _TryUntarring(tar_file_name): |
| """Try retrieving parts 2 and 3 from the passed in archive. |
| |
| Args: |
| tar_file_name: a string, file name of the tar file which is supposed to |
| contain parts 2 and 3 of the specification. |
| |
| Returns: |
| A tuple of strings, two file names in case they were found in the archive |
| and successfully extracted. |
| """ |
| part2 = None |
| part3 = None |
| tar_extract_base = ['tar', '-C', TMP_DIR, '-f'] |
| |
| components = subprocess.check_output(['tar', 'tf', tar_file_name], |
| stderr=subprocess.STDOUT) |
| for name in components.splitlines(): |
| if re.search('part2', name, re.IGNORECASE): |
| subprocess.check_output(tar_extract_base + [tar_file_name, '-x', name], |
| stderr=subprocess.STDOUT) |
| part2 = os.path.join(TMP_DIR, name) |
| if re.search('part3', name, re.IGNORECASE): |
| subprocess.check_output(tar_extract_base + [tar_file_name, '-x', name], |
| stderr=subprocess.STDOUT) |
| part3 = os.path.join(TMP_DIR, name) |
| return part2, part3 |
| |
| |
| def _ParseCommandLine(args): |
| |
| """Process command line and determine input file names. |
| |
| Input files could be supplied by two different ways - as part of a tar |
| archive (in which case only one command line parameter is expected), or as |
| two separate file names, one for part 2 and one for part 3. |
| |
| If a single command line parameter is supplied, and it is not '-h', tar |
| extraction is attempted and if successful, two separate files are created in |
| TMP_DIR. |
| |
| Args: |
| args: a list of string, command line parameters retrieved from sys.argv |
| |
| Returns: |
| A tuple of two strings, two html files to process, part 2 and part 3 of |
| the spec. |
| |
| Raises: |
| GeneratorException: on input errors. |
| """ |
| if len(args) == 1: |
| if args[0] == '-h': |
| print(usage) |
| sys.exit(0) |
| try: |
| structures_file, commands_file = _TryUntarring(args[0]) |
| except subprocess.CalledProcessError as e: |
| raise GeneratorException("command '%s' failed:\n%s\n%s" % |
| (' '.join(e.cmd), e.output, usage)) |
| |
| elif len(args) == 2: |
| structures_file = args[0] |
| commands_file = args[1] |
| else: |
| raise GeneratorException(usage) |
| return structures_file, commands_file |
| |
| |
| def main(argv): |
| """A Main function. |
| |
| TPM structures and commands files are parsed and C header and C implementation |
| files are generated. |
| |
| Args: |
| argv: a list of strings, command line parameters. |
| """ |
| |
| structures_file, commands_file = _ParseCommandLine(argv[1:]) |
| print('parse part2...') |
| html_parser = extract_structures.SpecParser() |
| tpm_table = html_parser.GetTable() |
| # The tables included in the below tuple are defined twice in the |
| # specification, once in part 2 and once in part 4. Let's ignore the part 2 |
| # definitions to avoid collisions. |
| tpm_table.SetSkipTables((2, 6, 9, 10, 13)) |
| html_parser.feed(open(structures_file).read()) |
| html_parser.close() |
| tpm_defines = tpm_table.GetHFile() |
| |
| print('parse part3...') |
| tpm_table.SetSkipTables(()) |
| html_parser.feed(open(commands_file).read()) |
| html_parser.close() |
| |
| # Move to the root directory, which is one level above the script. |
| os.chdir(os.path.join(os.path.dirname(argv[0]), '..')) |
| |
| # Save types include file. |
| print('generate output...') |
| types_file = open(TYPES_FILE, 'w') |
| guard_name = TYPES_FILE.upper() |
| guard_name = guard_name.replace('.', '_') |
| guard_name = 'TPM2_' + guard_name + '_' |
| types_file.write((structure_generator.COPYRIGHT_HEADER + |
| structure_generator.HEADER_FILE_GUARD_HEADER) % |
| {'name': guard_name}) |
| types_file.write(tpm_defines) |
| types_file.write((structure_generator.HEADER_FILE_GUARD_FOOTER) % |
| {'name': guard_name}) |
| types_file.close() |
| typemap = tpm_table.GetTypeMap() |
| structure_generator.GenerateHeader(typemap) |
| structure_generator.GenerateImplementation(typemap) |
| commands = tpm_table.GetCommandList() |
| command_generator.GenerateHeader(commands) |
| command_generator.GenerateImplementation(commands, typemap) |
| print('Processed %d TPM types.' % len(typemap)) |
| print('Processed %d commands.' % len(commands)) |
| |
| if __name__ == '__main__': |
| try: |
| main(sys.argv) |
| except GeneratorException as e: |
| if e.message: |
| print(e, file=sys.stderr) |
| sys.exit(1) |