676 lines
24 KiB
Python
Executable file
676 lines
24 KiB
Python
Executable file
# Copyright 2014 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 code generator for TPM 2.0 commands.
|
|
|
|
The command generator takes as input a list of command objects generated by
|
|
parsing the TCG specification and outputs valid C code to marshal command
|
|
input and output structures, and also generates functions ParseHandleBuffer
|
|
and CommandDispatcher defined by the TCG TPM2.0 Library Specification.
|
|
|
|
"""
|
|
|
|
from __future__ import print_function
|
|
|
|
import re
|
|
from subprocess import call
|
|
|
|
from structure_generator import COPYRIGHT_HEADER
|
|
from structure_generator import Field
|
|
|
|
_HEADER_FILE_GUARD_HEADER = """
|
|
#ifndef TPM2_%(name)s_FP_H_
|
|
#define TPM2_%(name)s_FP_H_
|
|
"""
|
|
_HEADER_FILE_GUARD_FOOTER = """
|
|
#endif // TPM2_%(name)s_FP_H
|
|
"""
|
|
_HEADER_FILE_INCLUDES = """
|
|
#include "tpm_generated.h"
|
|
"""
|
|
_IMPLEMENTATION_FILE_INCLUDES = """
|
|
#include "MemoryLib_fp.h"
|
|
#include "%(command_name)s_fp.h"
|
|
"""
|
|
_COMMAND_DISPATCHER_INCLUDES = '#include "%(command_name)s_fp.h"\n'
|
|
_COMMAND_DISPATCHER_START = """
|
|
#include "Implementation.h"
|
|
#include "CommandDispatcher_fp.h"
|
|
|
|
TPM_RC CommandDispatcher(
|
|
TPMI_ST_COMMAND_TAG tag,
|
|
TPM_CC command_code,
|
|
INT32 *request_parameter_buffer_size,
|
|
BYTE *request_parameter_buffer_start,
|
|
TPM_HANDLE request_handles[],
|
|
UINT32 *response_handle_buffer_size,
|
|
UINT32 *response_parameter_buffer_size) {
|
|
BYTE *request_parameter_buffer = request_parameter_buffer_start;
|
|
switch(command_code) {"""
|
|
_COMMAND_DISPATCHER_CASE = """
|
|
#ifdef %(command_code)s
|
|
case %(command_code)s:
|
|
return Exec_%(command_name)s(tag, &request_parameter_buffer,
|
|
request_parameter_buffer_size, request_handles,
|
|
response_handle_buffer_size, response_parameter_buffer_size);
|
|
#endif"""
|
|
_COMMAND_DISPATCHER_END = """
|
|
default:
|
|
return TPM_RC_COMMAND_CODE;
|
|
}
|
|
}"""
|
|
_HANDLE_PROCESS_START = """
|
|
#include "tpm_generated.h"
|
|
#include "HandleProcess_fp.h"
|
|
#include "Implementation.h"
|
|
#include "TPM_Types.h"
|
|
|
|
TPM_RC ParseHandleBuffer(
|
|
TPM_CC command_code,
|
|
BYTE **request_handle_buffer_start,
|
|
INT32 *request_buffer_remaining_size,
|
|
TPM_HANDLE request_handles[],
|
|
UINT32 *num_request_handles) {
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
*num_request_handles = 0;
|
|
switch(command_code) {
|
|
"""
|
|
_HANDLE_PROCESS_CASE_START = """
|
|
#ifdef %(command_code)s
|
|
case %(command_code)s:"""
|
|
_HANDLE_PROCESS_CASE_UNMARSHAL = """
|
|
result = %(handle_type)s_Unmarshal(
|
|
(%(handle_type)s*)&request_handles[*num_request_handles],
|
|
request_handle_buffer_start,
|
|
request_buffer_remaining_size);"""
|
|
_HANDLE_PROCESS_CASE_UNMARSHAL_FLAG = """
|
|
result = %(handle_type)s_Unmarshal(
|
|
(%(handle_type)s*)&request_handles[*num_request_handles],
|
|
request_handle_buffer_start,
|
|
request_buffer_remaining_size,
|
|
%(flag_val)s);"""
|
|
_HANDLE_PROCESS_CASE_CHECK = """
|
|
if (result != TPM_RC_SUCCESS) {
|
|
return result;
|
|
}
|
|
++(*num_request_handles);"""
|
|
_HANDLE_PROCESS_CASE_END = """
|
|
return TPM_RC_SUCCESS;
|
|
#endif"""
|
|
_HANDLE_PROCESS_END = """
|
|
default:
|
|
return TPM_RC_COMMAND_CODE;
|
|
}
|
|
}"""
|
|
_GET_COMMAND_CODE_STRING_HEADER = """
|
|
#ifndef TPM2_GET_COMMAND_CODE_STRING_FP_H_
|
|
#define TPM2_GET_COMMAND_CODE_STRING_FP_H_
|
|
|
|
#include "TPM_Types.h"
|
|
|
|
const char* GetCommandCodeString(TPM_CC command_code);
|
|
|
|
#endif // TPM2_GET_COMMAND_CODE_STRING_FP_H_"""
|
|
_GET_COMMAND_CODE_STRING_START = """
|
|
#include "GetCommandCodeString_fp.h"
|
|
|
|
const char* GetCommandCodeString(TPM_CC command_code) {
|
|
switch(command_code) {"""
|
|
_GET_COMMAND_CODE_STRING_CASE = """
|
|
#ifdef TPM_CC_%(command_name)s
|
|
case TPM_CC_%(command_name)s:
|
|
return "%(command_name)s";
|
|
#endif"""
|
|
_GET_COMMAND_CODE_STRING_END = """
|
|
default:
|
|
return "Unknown command";
|
|
}
|
|
}"""
|
|
|
|
|
|
class Command(object):
|
|
"""Represents a TPM command.
|
|
|
|
Attributes:
|
|
name: The command name (e.g. 'TPM2_Startup').
|
|
command_code: The name of the command code constant (e.g. TPM2_CC_Startup).
|
|
request_args: A list to hold command input arguments. Each element is a dict
|
|
and has these keys:
|
|
'type': The argument type.
|
|
'name': The argument name.
|
|
'command_code': The optional value of the command code constant.
|
|
'description': Optional descriptive text for the argument.
|
|
'has_conditional': String literal 'TRUE' or 'FALSE' indicating
|
|
whether 'type' is allowed to have a conditional value.
|
|
response_args: A list identical in form to request_args but to hold command
|
|
output arguments.
|
|
"""
|
|
|
|
_HANDLE_RE = re.compile(r'TPMI_.H_.*')
|
|
_STRUCT_DECL_START = """
|
|
typedef struct {"""
|
|
_STRUCT_DECL_FIELD = """
|
|
%(type)s %(name)s;"""
|
|
_STRUCT_DECL_END = """
|
|
} %(command_name)s_%(direction)s;
|
|
"""
|
|
_FUNCTION_DECL_IN_OUT = """
|
|
// Executes %(command_name)s with request handles and parameters from
|
|
// |in| and computes response handles and parameters to |out|.
|
|
TPM_RC TPM2_%(command_name)s(
|
|
%(command_name)s_In *in,
|
|
%(command_name)s_Out *out);
|
|
|
|
// Initializes handle fields in |target| from |request_handles|. Unmarshals
|
|
// parameter fields in |target| from |buffer|.
|
|
TPM_RC %(command_name)s_In_Unmarshal(
|
|
%(command_name)s_In *target,
|
|
TPM_HANDLE request_handles[],
|
|
BYTE **buffer,
|
|
INT32 *size);
|
|
|
|
// Marshals response handles and parameters from |source| to |buffer|. Computes
|
|
// and marshals the size of the parameter area (parameter_size) if |tag| ==
|
|
// TPM_ST_SESSIONS. Returns size of (parameter area + handle area) in bytes.
|
|
// Return value does not include parameter_size field.
|
|
UINT16 %(command_name)s_Out_Marshal(
|
|
%(command_name)s_Out *source,
|
|
TPMI_ST_COMMAND_TAG tag,
|
|
BYTE **buffer,
|
|
INT32 *size);
|
|
"""
|
|
_FUNCTION_DECL_IN = """
|
|
// Executes %(command_name)s with request handles and parameters from |in|.
|
|
TPM_RC TPM2_%(command_name)s(
|
|
%(command_name)s_In *in);
|
|
|
|
// Initializes handle fields in |target| from |request_handles|. Unmarshals
|
|
// parameter fields in |target| from |buffer|.
|
|
TPM_RC %(command_name)s_In_Unmarshal(
|
|
%(command_name)s_In *target,
|
|
TPM_HANDLE request_handles[],
|
|
BYTE **buffer,
|
|
INT32 *size);
|
|
"""
|
|
_FUNCTION_DECL_OUT = """
|
|
// Executes %(command_name)s and computes response handles and parameters
|
|
// to |out|.
|
|
TPM_RC TPM2_%(command_name)s(
|
|
%(command_name)s_Out *out);
|
|
|
|
// Marshals response handles and parameters from |source| to |buffer|. Computes
|
|
// and marshals the size of the parameter area (parameter_size) if |tag| ==
|
|
// TPM_ST_SESSIONS. Returns size of (parameter area + handle area) in bytes.
|
|
// Does not include parameter_size field.
|
|
UINT16 %(command_name)s_Out_Marshal(
|
|
%(command_name)s_Out *source,
|
|
TPMI_ST_COMMAND_TAG tag,
|
|
BYTE **buffer,
|
|
INT32 *size);
|
|
"""
|
|
_EXEC_DECL = """
|
|
// Unmarshals any request parameters starting at |request_parameter_buffer|.
|
|
// Executes command. Marshals any response handles and parameters to the
|
|
// global response buffer and computes |*response_handle_buffer_size| and
|
|
// |*response_parameter_buffer_size|. If |tag| == TPM_ST_SESSIONS, marshals
|
|
// parameter_size indicating the size of the parameter area. parameter_size
|
|
// field is located between the handle area and parameter area.
|
|
TPM_RC Exec_%(command_name)s(
|
|
TPMI_ST_COMMAND_TAG tag,
|
|
BYTE **request_parameter_buffer,
|
|
INT32 *request_parameter_buffer_size,
|
|
TPM_HANDLE request_handles[],
|
|
UINT32 *response_handle_buffer_size,
|
|
UINT32 *response_parameter_buffer_size);
|
|
"""
|
|
_EXEC_COMMAND_IMPL_START = """
|
|
TPM_RC Exec_%(command_name)s(
|
|
TPMI_ST_COMMAND_TAG tag,
|
|
BYTE **request_parameter_buffer,
|
|
INT32 *request_parameter_buffer_size,
|
|
TPM_HANDLE request_handles[],
|
|
UINT32 *response_handle_buffer_size,
|
|
UINT32 *response_parameter_buffer_size) {
|
|
TPM_RC result = TPM_RC_SUCCESS;"""
|
|
_EXEC_COMMAND_IMPL_IN_OUT = """
|
|
%(command_name)s_In in;
|
|
%(command_name)s_Out out;
|
|
#ifdef %(command_code)s
|
|
BYTE *response_buffer;
|
|
INT32 response_buffer_size;
|
|
UINT16 bytes_marshalled;
|
|
UINT16 num_response_handles = %(num_response_handles)s;
|
|
#endif
|
|
*response_handle_buffer_size = 0;
|
|
*response_parameter_buffer_size = 0;
|
|
// Unmarshal request parameters to input structure.
|
|
result = %(command_name)s_In_Unmarshal(&in, request_handles,
|
|
request_parameter_buffer, request_parameter_buffer_size);
|
|
if (result != TPM_RC_SUCCESS) {
|
|
return result;
|
|
}
|
|
// Execute command.
|
|
result = TPM2_%(command_name)s(&in, &out);
|
|
if (result != TPM_RC_SUCCESS) {
|
|
return result;
|
|
}
|
|
// Marshal output structure to global response buffer.
|
|
#ifdef %(command_code)s
|
|
response_buffer = MemoryGetResponseBuffer(%(command_code)s) + 10;
|
|
response_buffer_size = MAX_RESPONSE_SIZE - 10;
|
|
bytes_marshalled = %(command_name)s_Out_Marshal(
|
|
&out, tag, &response_buffer, &response_buffer_size);
|
|
*response_handle_buffer_size = num_response_handles*sizeof(TPM_HANDLE);
|
|
*response_parameter_buffer_size =
|
|
bytes_marshalled - *response_handle_buffer_size;
|
|
return TPM_RC_SUCCESS;
|
|
#endif
|
|
return TPM_RC_COMMAND_CODE;
|
|
}
|
|
"""
|
|
_EXEC_COMMAND_IMPL_IN = """
|
|
%(command_name)s_In in;
|
|
#ifdef %(command_code)s
|
|
BYTE *response_buffer;
|
|
INT32 response_buffer_size;
|
|
#endif
|
|
*response_handle_buffer_size = 0;
|
|
*response_parameter_buffer_size = 0;
|
|
// Unmarshal request parameters to input structure.
|
|
result = %(command_name)s_In_Unmarshal(&in, request_handles,
|
|
request_parameter_buffer, request_parameter_buffer_size);
|
|
if (result != TPM_RC_SUCCESS) {
|
|
return result;
|
|
}
|
|
// Execute command.
|
|
result = TPM2_%(command_name)s(&in);
|
|
if (result != TPM_RC_SUCCESS) {
|
|
return result;
|
|
}
|
|
#ifdef %(command_code)s
|
|
response_buffer = MemoryGetResponseBuffer(%(command_code)s) + 10;
|
|
response_buffer_size = MAX_RESPONSE_SIZE - 10;
|
|
// Add parameter_size field, always equal to 0 here.
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
UINT32_Marshal(response_parameter_buffer_size, &response_buffer,
|
|
&response_buffer_size);
|
|
}
|
|
return TPM_RC_SUCCESS;
|
|
#endif
|
|
return TPM_RC_COMMAND_CODE;
|
|
}
|
|
"""
|
|
_EXEC_COMMAND_IMPL_OUT = """
|
|
%(command_name)s_Out out;
|
|
#ifdef %(command_code)s
|
|
BYTE *response_buffer;
|
|
INT32 response_buffer_size;
|
|
UINT16 bytes_marshalled;
|
|
UINT16 num_response_handles = %(num_response_handles)s;
|
|
#endif
|
|
*response_handle_buffer_size = 0;
|
|
*response_parameter_buffer_size = 0;
|
|
// Execute command.
|
|
result = TPM2_%(command_name)s(&out);
|
|
if (result != TPM_RC_SUCCESS) {
|
|
return result;
|
|
}
|
|
// Marshal output structure containing response handles and parameters to
|
|
// response buffer.
|
|
#ifdef %(command_code)s
|
|
response_buffer = MemoryGetResponseBuffer(%(command_code)s) + 10;
|
|
response_buffer_size = MAX_RESPONSE_SIZE - 10;
|
|
bytes_marshalled = %(command_name)s_Out_Marshal(
|
|
&out, tag, &response_buffer, &response_buffer_size);
|
|
*response_handle_buffer_size = num_response_handles*sizeof(TPM_HANDLE);
|
|
*response_parameter_buffer_size =
|
|
bytes_marshalled - *response_handle_buffer_size;
|
|
return TPM_RC_SUCCESS;
|
|
#endif
|
|
return TPM_RC_COMMAND_CODE;
|
|
}
|
|
"""
|
|
_UNMARSHAL_COMMAND_START = """
|
|
TPM_RC %(command_name)s_In_Unmarshal(
|
|
%(command_name)s_In *target,
|
|
TPM_HANDLE request_handles[],
|
|
BYTE **buffer,
|
|
INT32 *size) {
|
|
TPM_RC result = TPM_RC_SUCCESS;"""
|
|
_MARSHAL_COMMAND_START = """
|
|
UINT16 %(command_name)s_Out_Marshal(
|
|
%(command_name)s_Out *source,
|
|
TPMI_ST_COMMAND_TAG tag,
|
|
BYTE **buffer,
|
|
INT32 *size) {
|
|
UINT16 total_size = 0;
|
|
UINT32 parameter_size = 0;
|
|
BYTE *parameter_size_location;
|
|
INT32 parameter_size_size = sizeof(UINT32);
|
|
UINT32 num_response_handles = %(num_response_handles)s;"""
|
|
_UNMARSHAL_END = """
|
|
if ((result == TPM_RC_SUCCESS) && *size) {
|
|
result = TPM_RC_SIZE;
|
|
}
|
|
return result;
|
|
}
|
|
"""
|
|
_MARSHAL_END = """
|
|
// Compute actual parameter_size. Don't add result to total_size.
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
parameter_size = total_size - num_response_handles*sizeof(TPM_HANDLE);
|
|
UINT32_Marshal(
|
|
¶meter_size, ¶meter_size_location, ¶meter_size_size);
|
|
}
|
|
return total_size;
|
|
}
|
|
"""
|
|
_SET_COMMAND_HANDLE = """
|
|
target->%(field_name)s = request_handles[%(num)s];"""
|
|
_PARAMETERSIZE_CHECK = """
|
|
// Add parameter_size=0 to indicate size of the parameter area. Will be
|
|
// replaced later by computed parameter_size.
|
|
if (tag == TPM_ST_SESSIONS) {
|
|
parameter_size_location = *buffer;
|
|
// Don't add to total_size, but increment *buffer and decrement *size.
|
|
UINT32_Marshal(¶meter_size, buffer, size);
|
|
}"""
|
|
|
|
def __init__(self, name):
|
|
"""Initializes a Command instance.
|
|
|
|
Initially the request_args and response_args attributes are not set.
|
|
|
|
Args:
|
|
name: The command name (e.g. 'TPM2_Startup').
|
|
"""
|
|
self.name = name
|
|
self.request_args = None
|
|
self.response_args = None
|
|
if name.startswith('TPM2_'):
|
|
self.command_code = name.replace('TPM2_', 'TPM_CC_')
|
|
else:
|
|
self.command_code = ''
|
|
|
|
def __str__(self):
|
|
s = ['%s:' % self.name,]
|
|
if self.request_args:
|
|
s.append(' req:')
|
|
for r in self.request_args:
|
|
s.append(' %s: %s' % (r['type'], r['name']))
|
|
if self.response_args:
|
|
s.append(' resp:')
|
|
for r in self.response_args:
|
|
s.append(' %s: %s' % (r['type'], r['name']))
|
|
s.append('')
|
|
return '\n'.join(s)
|
|
|
|
def OutputMarshalFunction(self, out_file, typemap):
|
|
"""Generates a marshal function for the command output structure.
|
|
|
|
Args:
|
|
out_file: File to be written to opened by the caller.
|
|
typemap: A dict mapping type names to the corresponding object.
|
|
Generated by structure_generator.
|
|
"""
|
|
if not self.response_args:
|
|
return
|
|
# Categorize arguments as either handles or parameters.
|
|
handles, parameters = self._SplitArgs(self.response_args)
|
|
out_file.write(self._MARSHAL_COMMAND_START % {
|
|
'command_name': self.MethodName(),
|
|
'num_response_handles': self._GetNumberOfResponseHandles()})
|
|
if handles:
|
|
out_file.write('\n // Marshal response handles.')
|
|
for handle in handles:
|
|
typemap[handle['type']].OutputMarshalCall(
|
|
out_file, Field(handle['type'],
|
|
handle['name'],
|
|
conditional_value=handle['has_conditional']))
|
|
out_file.write(self._PARAMETERSIZE_CHECK)
|
|
if parameters:
|
|
out_file.write('\n // Marshal response parameters.')
|
|
for parameter in parameters:
|
|
typemap[parameter['type']].OutputMarshalCall(
|
|
out_file, Field(parameter['type'], parameter['name'],
|
|
conditional_value=parameter['has_conditional']))
|
|
out_file.write(self._MARSHAL_END)
|
|
|
|
def OutputUnmarshalFunction(self, out_file, typemap):
|
|
"""Generates a unmarshal function for the command input structure.
|
|
|
|
Args:
|
|
out_file: File to be written to opened by the caller.
|
|
typemap: A dict mapping type names to the corresponding object.
|
|
Generated by structure_generator.
|
|
"""
|
|
if not self.request_args:
|
|
return
|
|
# Categorize arguments as either handles or parameters.
|
|
handles, parameters = self._SplitArgs(self.request_args)
|
|
out_file.write(self._UNMARSHAL_COMMAND_START % {
|
|
'command_name': self.MethodName()})
|
|
if handles:
|
|
out_file.write('\n // Get request handles from request_handles array.')
|
|
for index, handle in enumerate(handles):
|
|
out_file.write(self._SET_COMMAND_HANDLE % {'field_name': handle['name'],
|
|
'num': index})
|
|
if parameters:
|
|
out_file.write('\n // Unmarshal request parameters.')
|
|
for parameter in parameters:
|
|
typemap[parameter['type']].OutputUnmarshalCall(
|
|
out_file, Field(parameter['type'],
|
|
parameter['name'],
|
|
conditional_value=parameter['has_conditional']))
|
|
out_file.write(self._UNMARSHAL_END)
|
|
|
|
def OutputExecFunction(self, out_file):
|
|
"""Generates an exec function for the command.
|
|
|
|
Args:
|
|
out_file: File to be written to opened by the caller.
|
|
"""
|
|
out_file.write(
|
|
self._EXEC_COMMAND_IMPL_START % {'command_name': self.MethodName()})
|
|
if self.request_args and self.response_args:
|
|
out_file.write(self._EXEC_COMMAND_IMPL_IN_OUT % {
|
|
'command_name': self.MethodName(),
|
|
'command_code': self.command_code,
|
|
'num_response_handles': self._GetNumberOfResponseHandles()})
|
|
elif self.request_args:
|
|
out_file.write(self._EXEC_COMMAND_IMPL_IN % {
|
|
'command_name': self.MethodName(),
|
|
'command_code': self.command_code})
|
|
elif self.response_args:
|
|
out_file.write(self._EXEC_COMMAND_IMPL_OUT % {
|
|
'command_name': self.MethodName(),
|
|
'command_code': self.command_code,
|
|
'num_response_handles': self._GetNumberOfResponseHandles()})
|
|
|
|
def OutputDecl(self, out_file):
|
|
"""Generates a TPM object declaration."""
|
|
if self.request_args:
|
|
out_file.write(self._STRUCT_DECL_START)
|
|
for arg in self.request_args:
|
|
out_file.write(self._STRUCT_DECL_FIELD % {'type': arg['type'],
|
|
'name': arg['name']})
|
|
out_file.write(self._STRUCT_DECL_END % {'command_name': self.MethodName(),
|
|
'direction': 'In'})
|
|
if self.response_args:
|
|
out_file.write(self._STRUCT_DECL_START)
|
|
for arg in self.response_args:
|
|
out_file.write(self._STRUCT_DECL_FIELD % {'type': arg['type'],
|
|
'name': arg['name']})
|
|
out_file.write(self._STRUCT_DECL_END % {'command_name': self.MethodName(),
|
|
'direction': 'Out'})
|
|
if len(self.response_args) and len(self.request_args):
|
|
out_file.write(
|
|
self._FUNCTION_DECL_IN_OUT % {'command_name': self.MethodName()})
|
|
elif self.response_args:
|
|
out_file.write(
|
|
self._FUNCTION_DECL_OUT % {'command_name': self.MethodName()})
|
|
elif self.request_args:
|
|
out_file.write(
|
|
self._FUNCTION_DECL_IN % {'command_name': self.MethodName()})
|
|
out_file.write(self._EXEC_DECL % {'command_name': self.MethodName()})
|
|
|
|
def _GetNumberOfRequestHandles(self):
|
|
"""Returns the number of input handles for this command."""
|
|
return len(self._SplitArgs(self.request_args)[0])
|
|
|
|
def _GetNumberOfResponseHandles(self):
|
|
"""Returns the number of output handles for this command."""
|
|
return len(self._SplitArgs(self.response_args)[0])
|
|
|
|
def MethodName(self):
|
|
"""Creates an appropriate generated method name for the command.
|
|
|
|
We use the command name without the TPM2_ prefix.
|
|
|
|
Returns:
|
|
The method name.
|
|
"""
|
|
if not self.name.startswith('TPM2_'):
|
|
return self.name
|
|
return self.name[5:]
|
|
|
|
def GetRequestHandles(self):
|
|
"""Returns a list of input handles for this command."""
|
|
return self._SplitArgs(self.request_args)[0]
|
|
|
|
def _SplitArgs(self, args):
|
|
"""Splits a list of args into handles and parameters."""
|
|
always_params = {
|
|
'TPM_CC_FlushContext': 'TPMI_DH_CONTEXT',
|
|
'TPM_CC_Hash': 'TPMI_RH_HIERARCHY',
|
|
'TPM_CC_LoadExternal': 'TPMI_RH_HIERARCHY',
|
|
'TPM_CC_SequenceComplete': 'TPMI_RH_HIERARCHY',
|
|
}
|
|
handles = []
|
|
parameters = []
|
|
always_handle = set(['TPM_HANDLE'])
|
|
# Handle types that appear as command parameters.
|
|
always_parameter = set(['TPMI_RH_ENABLES', 'TPMI_DH_PERSISTENT'])
|
|
if self.command_code in always_params:
|
|
always_parameter.add(always_params[self.command_code])
|
|
for arg in args:
|
|
if (arg['type'] in always_handle or
|
|
(self._HANDLE_RE.search(arg['type']) and
|
|
arg['type'] not in always_parameter)):
|
|
handles.append(arg)
|
|
else:
|
|
parameters.append(arg)
|
|
return handles, parameters
|
|
|
|
|
|
def _OutputCommandDispatcher(commands):
|
|
"""Generates implementation file for CommandDispatcher function.
|
|
|
|
Args:
|
|
commands: A list of Command objects.
|
|
"""
|
|
with open('CommandDispatcher.c', 'w') as out_file:
|
|
out_file.write(COPYRIGHT_HEADER)
|
|
for command in commands:
|
|
out_file.write(_COMMAND_DISPATCHER_INCLUDES %
|
|
{'command_name': command.MethodName()})
|
|
out_file.write(_COMMAND_DISPATCHER_START)
|
|
for command in commands:
|
|
command_code = 'TPM_CC_' + command.MethodName()
|
|
out_file.write(_COMMAND_DISPATCHER_CASE %
|
|
{'command_code': command_code,
|
|
'command_name': command.MethodName()})
|
|
out_file.write(_COMMAND_DISPATCHER_END)
|
|
call(['clang-format', '-i', '-style=Chromium', 'CommandDispatcher.c'])
|
|
|
|
|
|
def _OutputHandleProcess(commands, typemap):
|
|
"""Generates implementation file for ParseHandleBuffer function.
|
|
|
|
Args:
|
|
commands: A list of Command objects.
|
|
typemap: A dict mapping type names to the corresponding object.
|
|
Generated by structure_generator.
|
|
"""
|
|
with open('HandleProcess.c', 'w') as out_file:
|
|
out_file.write(COPYRIGHT_HEADER)
|
|
out_file.write(_HANDLE_PROCESS_START)
|
|
for command in commands:
|
|
command_code = 'TPM_CC_' + command.MethodName()
|
|
out_file.write(_HANDLE_PROCESS_CASE_START %
|
|
{'command_code': command_code})
|
|
for handle in command.GetRequestHandles():
|
|
if typemap[handle['type']].HasConditional():
|
|
out_file.write(_HANDLE_PROCESS_CASE_UNMARSHAL_FLAG %
|
|
{'handle_type': handle['type'],
|
|
'flag_val': handle['has_conditional']})
|
|
else:
|
|
out_file.write(_HANDLE_PROCESS_CASE_UNMARSHAL %
|
|
{'handle_type': handle['type']})
|
|
out_file.write(_HANDLE_PROCESS_CASE_CHECK)
|
|
out_file.write(_HANDLE_PROCESS_CASE_END)
|
|
out_file.write(_HANDLE_PROCESS_END)
|
|
call(['clang-format', '-i', '-style=Chromium', 'HandleProcess.c'])
|
|
|
|
|
|
def _OutputGetCommandCodeString(commands):
|
|
"""Generates header and implementation files for GetCommandCodeString.
|
|
|
|
Args:
|
|
commands: A list of Command objects.
|
|
"""
|
|
with open('GetCommandCodeString_fp.h', 'w') as out_file:
|
|
out_file.write(COPYRIGHT_HEADER)
|
|
out_file.write(_GET_COMMAND_CODE_STRING_HEADER)
|
|
call(['clang-format', '-i', '-style=Chromium', 'GetCommandCodeString_fp.h'])
|
|
with open('GetCommandCodeString.c', 'w') as out_file:
|
|
out_file.write(COPYRIGHT_HEADER)
|
|
out_file.write(_GET_COMMAND_CODE_STRING_START)
|
|
for command in commands:
|
|
out_file.write(_GET_COMMAND_CODE_STRING_CASE %
|
|
{'command_name': command.MethodName()})
|
|
out_file.write(_GET_COMMAND_CODE_STRING_END)
|
|
call(['clang-format', '-i', '-style=Chromium', 'GetCommandCodeString.c'])
|
|
|
|
|
|
def GenerateHeader(commands):
|
|
"""Generates a header file with declarations for all given generator objects.
|
|
|
|
Args:
|
|
commands: A list of Command objects.
|
|
"""
|
|
for command in commands:
|
|
command_header_file = command.MethodName()+'_fp.h'
|
|
with open(command_header_file, 'w') as out_file:
|
|
out_file.write(COPYRIGHT_HEADER)
|
|
out_file.write(
|
|
_HEADER_FILE_GUARD_HEADER % {'name': command.MethodName().upper()})
|
|
out_file.write(_HEADER_FILE_INCLUDES)
|
|
command.OutputDecl(out_file)
|
|
out_file.write(
|
|
_HEADER_FILE_GUARD_FOOTER % {'name': command.MethodName().upper()})
|
|
call(['clang-format', '-i', '-style=Chromium', command_header_file])
|
|
|
|
|
|
def GenerateImplementation(commands, typemap):
|
|
"""Generates implementation code for each command.
|
|
|
|
Args:
|
|
commands: A list of Command objects.
|
|
typemap: A dict mapping type names to the corresponding object.
|
|
Generated by structure_generator.
|
|
"""
|
|
for command in commands:
|
|
marshal_command_file = 'Marshal_'+command.MethodName()+'.c'
|
|
with open(marshal_command_file, 'w') as out_file:
|
|
out_file.write(COPYRIGHT_HEADER)
|
|
out_file.write(_IMPLEMENTATION_FILE_INCLUDES %
|
|
{'command_name': command.MethodName()})
|
|
command.OutputMarshalFunction(out_file, typemap)
|
|
command.OutputUnmarshalFunction(out_file, typemap)
|
|
command.OutputExecFunction(out_file)
|
|
call(['clang-format', '-i', '-style=Chromium', marshal_command_file])
|
|
_OutputHandleProcess(commands, typemap)
|
|
_OutputCommandDispatcher(commands)
|
|
_OutputGetCommandCodeString(commands)
|