mirror of
https://github.com/DreamSourceLab/DSView.git
synced 2025-01-23 13:42:55 +08:00
Merge branch 'master' of https://github.com/dreamsourcelab/DSView
This commit is contained in:
commit
6a0f1b8cf8
28
libsigrokdecode4DSL/decoders/spi_tpm/README.md
Normal file
28
libsigrokdecode4DSL/decoders/spi_tpm/README.md
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# libsigrokdecoder_spi-tpm
|
||||||
|
|
||||||
|
libsigrok stacked Protocol Decoder for TPM 2.0 & TPM 1.2 transactions from an SPI bus.
|
||||||
|
BitLocker Volume Master Key (VMK) is automatically extracted.
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
|
||||||
|
### CLI
|
||||||
|
|
||||||
|
Example from a previous capture (Value Change Dump - .vcd format):
|
||||||
|
|
||||||
|
1. Identifying channels name:
|
||||||
|
|
||||||
|
`sigrok-cli -i capture.vcd --show`
|
||||||
|
|
||||||
|
2. Extracting BitLocker VMK (filter output to extract only VMK annotations)
|
||||||
|
|
||||||
|
`.\sigrok-cli.exe -i C:\Users\jovre\Documents\tpm_spi_comm_2.vcd -I vcd:numchannels=6 -P spi:wordsize=8:cs_polarity=active-high:miso=libsigrok4DSL.3:mosi=libsigrok4DSL.1:clk=libsigrok4DSL.2:cs=libsigrok4DSL.0,spi_tpm:tpm_version=1.2 -A spi_tpm=VMK`
|
||||||
|
|
||||||
|
***command output:***
|
||||||
|
|
||||||
|
`spi_tpm-1: VMK header: 2c0005000100000003200000`
|
||||||
|
|
||||||
|
`spi_tpm-1: VMK: 85e5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxee00`
|
||||||
|
|
||||||
|
### GUI
|
||||||
|
|
||||||
|
Use and configure the SPI Protocol Decoder and then select SPI TPM Stack Decoder.
|
@ -1,299 +1,299 @@
|
|||||||
# Source: https://raw.githubusercontent.com/WKPlus/rangedict/master/rangedict.py
|
# Source: https://raw.githubusercontent.com/WKPlus/rangedict/master/rangedict.py
|
||||||
__all__ = ['RangeDict']
|
__all__ = ['RangeDict']
|
||||||
|
|
||||||
|
|
||||||
class Color(object):
|
class Color(object):
|
||||||
BLACK = 0
|
BLACK = 0
|
||||||
RED = 1
|
RED = 1
|
||||||
|
|
||||||
|
|
||||||
class Node(object):
|
class Node(object):
|
||||||
__slots__ = ('r', 'left', 'right', 'value', 'color', 'parent')
|
__slots__ = ('r', 'left', 'right', 'value', 'color', 'parent')
|
||||||
|
|
||||||
def __init__(self, r, value, parent=None, color=Color.RED):
|
def __init__(self, r, value, parent=None, color=Color.RED):
|
||||||
self.r = r
|
self.r = r
|
||||||
self.value = value
|
self.value = value
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self.color = color
|
self.color = color
|
||||||
self.left = None
|
self.left = None
|
||||||
self.right = None
|
self.right = None
|
||||||
|
|
||||||
def value_copy(self, other):
|
def value_copy(self, other):
|
||||||
self.r = other.r
|
self.r = other.r
|
||||||
self.value = other.value
|
self.value = other.value
|
||||||
|
|
||||||
|
|
||||||
class RangeDict(dict):
|
class RangeDict(dict):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._root = None
|
self._root = None
|
||||||
|
|
||||||
def __setitem__(self, r, v):
|
def __setitem__(self, r, v):
|
||||||
if r[1] < r[0]:
|
if r[1] < r[0]:
|
||||||
raise KeyError
|
raise KeyError
|
||||||
node = self._insert(r, v)
|
node = self._insert(r, v)
|
||||||
self._insert_adjust(node)
|
self._insert_adjust(node)
|
||||||
|
|
||||||
def _insert(self, r, v):
|
def _insert(self, r, v):
|
||||||
if not self._root:
|
if not self._root:
|
||||||
self._root = Node(r, v)
|
self._root = Node(r, v)
|
||||||
return self._root
|
return self._root
|
||||||
cur = self._root
|
cur = self._root
|
||||||
while True:
|
while True:
|
||||||
if r[1] < cur.r[0]:
|
if r[1] < cur.r[0]:
|
||||||
if not cur.left:
|
if not cur.left:
|
||||||
cur.left = Node(r, v, cur)
|
cur.left = Node(r, v, cur)
|
||||||
return cur.left
|
return cur.left
|
||||||
cur = cur.left
|
cur = cur.left
|
||||||
elif r[0] > cur.r[1]:
|
elif r[0] > cur.r[1]:
|
||||||
if not cur.right:
|
if not cur.right:
|
||||||
cur.right = Node(r, v, cur)
|
cur.right = Node(r, v, cur)
|
||||||
return cur.right
|
return cur.right
|
||||||
cur = cur.right
|
cur = cur.right
|
||||||
else:
|
else:
|
||||||
raise KeyError # overlap not supported
|
raise KeyError # overlap not supported
|
||||||
|
|
||||||
def _insert_adjust(self, node):
|
def _insert_adjust(self, node):
|
||||||
''' adjust to make the tree still a red black tree '''
|
''' adjust to make the tree still a red black tree '''
|
||||||
if not node.parent:
|
if not node.parent:
|
||||||
node.color = Color.BLACK
|
node.color = Color.BLACK
|
||||||
return
|
return
|
||||||
if node.parent.color == Color.BLACK:
|
if node.parent.color == Color.BLACK:
|
||||||
return
|
return
|
||||||
uncle = self.sibling(node.parent)
|
uncle = self.sibling(node.parent)
|
||||||
if node_color(uncle) == Color.RED:
|
if node_color(uncle) == Color.RED:
|
||||||
node.parent.color = Color.BLACK
|
node.parent.color = Color.BLACK
|
||||||
uncle.color = Color.BLACK
|
uncle.color = Color.BLACK
|
||||||
node.parent.parent.color = Color.RED
|
node.parent.parent.color = Color.RED
|
||||||
return self._insert_adjust(node.parent.parent)
|
return self._insert_adjust(node.parent.parent)
|
||||||
|
|
||||||
#parent is red and uncle is black
|
#parent is red and uncle is black
|
||||||
# since parent is red, grandparent must exists and be black
|
# since parent is red, grandparent must exists and be black
|
||||||
parent = node.parent
|
parent = node.parent
|
||||||
grandparent = parent.parent
|
grandparent = parent.parent
|
||||||
if self.is_left_son(parent, grandparent):
|
if self.is_left_son(parent, grandparent):
|
||||||
if self.is_left_son(node, parent):
|
if self.is_left_son(node, parent):
|
||||||
self.right_rotate(grandparent)
|
self.right_rotate(grandparent)
|
||||||
grandparent.color = Color.RED
|
grandparent.color = Color.RED
|
||||||
parent.color = Color.BLACK
|
parent.color = Color.BLACK
|
||||||
else:
|
else:
|
||||||
self.left_rotate(parent)
|
self.left_rotate(parent)
|
||||||
self.right_rotate(grandparent)
|
self.right_rotate(grandparent)
|
||||||
grandparent.color = Color.RED
|
grandparent.color = Color.RED
|
||||||
node.color = Color.BLACK
|
node.color = Color.BLACK
|
||||||
else:
|
else:
|
||||||
if self.is_left_son(node, parent):
|
if self.is_left_son(node, parent):
|
||||||
self.right_rotate(parent)
|
self.right_rotate(parent)
|
||||||
self.left_rotate(grandparent)
|
self.left_rotate(grandparent)
|
||||||
grandparent.color = Color.RED
|
grandparent.color = Color.RED
|
||||||
node.color = Color.BLACK
|
node.color = Color.BLACK
|
||||||
else:
|
else:
|
||||||
self.left_rotate(grandparent)
|
self.left_rotate(grandparent)
|
||||||
grandparent.color = Color.RED
|
grandparent.color = Color.RED
|
||||||
parent.color = Color.BLACK
|
parent.color = Color.BLACK
|
||||||
|
|
||||||
def _find_key(self, key):
|
def _find_key(self, key):
|
||||||
cur = self._root
|
cur = self._root
|
||||||
while cur:
|
while cur:
|
||||||
if key > cur.r[1]:
|
if key > cur.r[1]:
|
||||||
cur = cur.right
|
cur = cur.right
|
||||||
elif key < cur.r[0]:
|
elif key < cur.r[0]:
|
||||||
cur = cur.left
|
cur = cur.left
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
return cur
|
return cur
|
||||||
|
|
||||||
def _find_range(self, r):
|
def _find_range(self, r):
|
||||||
cur = self._root
|
cur = self._root
|
||||||
while cur:
|
while cur:
|
||||||
if r[1] < cur.r[0]:
|
if r[1] < cur.r[0]:
|
||||||
cur = cur.left
|
cur = cur.left
|
||||||
elif r[0] > cur.r[1]:
|
elif r[0] > cur.r[1]:
|
||||||
cur = cur.right
|
cur = cur.right
|
||||||
elif r[0] == cur.r[0] and r[1] == cur.r[1]:
|
elif r[0] == cur.r[0] and r[1] == cur.r[1]:
|
||||||
return cur
|
return cur
|
||||||
else:
|
else:
|
||||||
raise KeyError
|
raise KeyError
|
||||||
raise KeyError
|
raise KeyError
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
tar = self._find_key(key)
|
tar = self._find_key(key)
|
||||||
if tar:
|
if tar:
|
||||||
return tar.value
|
return tar.value
|
||||||
raise KeyError
|
raise KeyError
|
||||||
|
|
||||||
def __contains__(self, key):
|
def __contains__(self, key):
|
||||||
return bool(self._find_key(key))
|
return bool(self._find_key(key))
|
||||||
|
|
||||||
def __delitem__(self, r):
|
def __delitem__(self, r):
|
||||||
node = self._find_range(r)
|
node = self._find_range(r)
|
||||||
if node.left and node.right:
|
if node.left and node.right:
|
||||||
left_rightest_child = self.find_rightest(node.left)
|
left_rightest_child = self.find_rightest(node.left)
|
||||||
node.value_copy(left_rightest_child)
|
node.value_copy(left_rightest_child)
|
||||||
node = left_rightest_child
|
node = left_rightest_child
|
||||||
self._delete(node)
|
self._delete(node)
|
||||||
|
|
||||||
def _delete(self, node):
|
def _delete(self, node):
|
||||||
# node has at most one child
|
# node has at most one child
|
||||||
child = node.left if node.left else node.right
|
child = node.left if node.left else node.right
|
||||||
if not node.parent: # node is root
|
if not node.parent: # node is root
|
||||||
self._root = child
|
self._root = child
|
||||||
if self._root:
|
if self._root:
|
||||||
self._root.parent = None
|
self._root.parent = None
|
||||||
self._root.color = Color.BLACK
|
self._root.color = Color.BLACK
|
||||||
return
|
return
|
||||||
|
|
||||||
parent = node.parent
|
parent = node.parent
|
||||||
if not child:
|
if not child:
|
||||||
child = Node(None, None, parent, Color.BLACK)
|
child = Node(None, None, parent, Color.BLACK)
|
||||||
if self.is_left_son(node, parent):
|
if self.is_left_son(node, parent):
|
||||||
parent.left = child
|
parent.left = child
|
||||||
else:
|
else:
|
||||||
parent.right = child
|
parent.right = child
|
||||||
child.parent = parent
|
child.parent = parent
|
||||||
|
|
||||||
if node.color == Color.RED:
|
if node.color == Color.RED:
|
||||||
# no need to adjust when deleting a red node
|
# no need to adjust when deleting a red node
|
||||||
return
|
return
|
||||||
if node_color(child) == Color.RED:
|
if node_color(child) == Color.RED:
|
||||||
child.color = Color.BLACK
|
child.color = Color.BLACK
|
||||||
return
|
return
|
||||||
self._delete_adjust(child)
|
self._delete_adjust(child)
|
||||||
if not child.r:
|
if not child.r:
|
||||||
# mock a None node for adjust, need to delete it after that
|
# mock a None node for adjust, need to delete it after that
|
||||||
parent = child.parent
|
parent = child.parent
|
||||||
if self.is_left_son(child, parent):
|
if self.is_left_son(child, parent):
|
||||||
parent.left = None
|
parent.left = None
|
||||||
else:
|
else:
|
||||||
parent.right = None
|
parent.right = None
|
||||||
|
|
||||||
def _delete_adjust(self, node):
|
def _delete_adjust(self, node):
|
||||||
if not node.parent:
|
if not node.parent:
|
||||||
node.color = Color.BLACK
|
node.color = Color.BLACK
|
||||||
return
|
return
|
||||||
|
|
||||||
parent = node.parent
|
parent = node.parent
|
||||||
sibling = self.sibling(node)
|
sibling = self.sibling(node)
|
||||||
if node_color(sibling) == Color.RED:
|
if node_color(sibling) == Color.RED:
|
||||||
if self.is_left_son(node, parent):
|
if self.is_left_son(node, parent):
|
||||||
self.left_rotate(parent)
|
self.left_rotate(parent)
|
||||||
else:
|
else:
|
||||||
self.right_rotate(parent)
|
self.right_rotate(parent)
|
||||||
parent.color = Color.RED
|
parent.color = Color.RED
|
||||||
sibling.color = Color.BLACK
|
sibling.color = Color.BLACK
|
||||||
sibling = self.sibling(node) # must be black
|
sibling = self.sibling(node) # must be black
|
||||||
|
|
||||||
# sibling must be black now
|
# sibling must be black now
|
||||||
if not self.is_black(parent) and self.is_black(sibling.left) and \
|
if not self.is_black(parent) and self.is_black(sibling.left) and \
|
||||||
self.is_black(sibling.right):
|
self.is_black(sibling.right):
|
||||||
parent.color = Color.BLACK
|
parent.color = Color.BLACK
|
||||||
sibling.color = Color.RED
|
sibling.color = Color.RED
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.is_black(parent) and self.is_black(sibling.left) and \
|
if self.is_black(parent) and self.is_black(sibling.left) and \
|
||||||
self.is_black(sibling.right):
|
self.is_black(sibling.right):
|
||||||
sibling.color = Color.RED
|
sibling.color = Color.RED
|
||||||
return self._delete_adjust(parent)
|
return self._delete_adjust(parent)
|
||||||
|
|
||||||
if self.is_left_son(node, parent):
|
if self.is_left_son(node, parent):
|
||||||
if not self.is_black(sibling.left) and \
|
if not self.is_black(sibling.left) and \
|
||||||
self.is_black(sibling.right):
|
self.is_black(sibling.right):
|
||||||
sibling.left.color = Color.BLACK
|
sibling.left.color = Color.BLACK
|
||||||
sibling.color = Color.RED
|
sibling.color = Color.RED
|
||||||
self.right_rotate(sibling)
|
self.right_rotate(sibling)
|
||||||
sibling = sibling.parent
|
sibling = sibling.parent
|
||||||
|
|
||||||
# sibling.right must be red
|
# sibling.right must be red
|
||||||
sibling.color = parent.color
|
sibling.color = parent.color
|
||||||
parent.color = Color.BLACK
|
parent.color = Color.BLACK
|
||||||
sibling.right.color = Color.BLACK
|
sibling.right.color = Color.BLACK
|
||||||
self.left_rotate(parent)
|
self.left_rotate(parent)
|
||||||
else:
|
else:
|
||||||
if not self.is_black(sibling.right) and \
|
if not self.is_black(sibling.right) and \
|
||||||
self.is_black(sibling.left):
|
self.is_black(sibling.left):
|
||||||
sibling.right.color = Color.BLACK
|
sibling.right.color = Color.BLACK
|
||||||
sibling.color = Color.RED
|
sibling.color = Color.RED
|
||||||
self.left_rotate(parent)
|
self.left_rotate(parent)
|
||||||
sibling = sibling.parent
|
sibling = sibling.parent
|
||||||
|
|
||||||
# sibling.left must be red
|
# sibling.left must be red
|
||||||
sibling.color = parent.color
|
sibling.color = parent.color
|
||||||
parent.color = Color.BLACK
|
parent.color = Color.BLACK
|
||||||
sibling.left.color = Color.RED
|
sibling.left.color = Color.RED
|
||||||
self.right_rotate(parent)
|
self.right_rotate(parent)
|
||||||
|
|
||||||
def left_rotate(self, node):
|
def left_rotate(self, node):
|
||||||
right_son = node.right
|
right_son = node.right
|
||||||
|
|
||||||
if not node.parent:
|
if not node.parent:
|
||||||
self._root = right_son
|
self._root = right_son
|
||||||
elif self.is_left_son(node, node.parent):
|
elif self.is_left_son(node, node.parent):
|
||||||
node.parent.left = right_son
|
node.parent.left = right_son
|
||||||
else:
|
else:
|
||||||
node.parent.right = right_son
|
node.parent.right = right_son
|
||||||
right_son.parent = node.parent
|
right_son.parent = node.parent
|
||||||
|
|
||||||
node.parent = right_son
|
node.parent = right_son
|
||||||
node.right = right_son.left
|
node.right = right_son.left
|
||||||
right_son.left = node
|
right_son.left = node
|
||||||
|
|
||||||
def right_rotate(self, node):
|
def right_rotate(self, node):
|
||||||
left_son = node.left
|
left_son = node.left
|
||||||
if not node.parent:
|
if not node.parent:
|
||||||
self._root = left_son
|
self._root = left_son
|
||||||
elif self.is_left_son(node, node.parent):
|
elif self.is_left_son(node, node.parent):
|
||||||
node.parent.left = left_son
|
node.parent.left = left_son
|
||||||
else:
|
else:
|
||||||
node.parent.right = left_son
|
node.parent.right = left_son
|
||||||
left_son.parent = node.parent
|
left_son.parent = node.parent
|
||||||
|
|
||||||
node.parent = left_son
|
node.parent = left_son
|
||||||
node.left = left_son.right
|
node.left = left_son.right
|
||||||
left_son.right = node
|
left_son.right = node
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def sibling(node):
|
def sibling(node):
|
||||||
if node.parent.left == node:
|
if node.parent.left == node:
|
||||||
return node.parent.right
|
return node.parent.right
|
||||||
else:
|
else:
|
||||||
return node.parent.left
|
return node.parent.left
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_left_son(child, parent):
|
def is_left_son(child, parent):
|
||||||
if parent.left == child:
|
if parent.left == child:
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def find_rightest(node):
|
def find_rightest(node):
|
||||||
while node.right:
|
while node.right:
|
||||||
node = node.right
|
node = node.right
|
||||||
return node
|
return node
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_black(node):
|
def is_black(node):
|
||||||
return node_color(node) == Color.BLACK
|
return node_color(node) == Color.BLACK
|
||||||
|
|
||||||
|
|
||||||
def node_color(node):
|
def node_color(node):
|
||||||
if not node:
|
if not node:
|
||||||
return Color.BLACK
|
return Color.BLACK
|
||||||
return node.color
|
return node.color
|
||||||
|
|
||||||
|
|
||||||
def in_order(root):
|
def in_order(root):
|
||||||
ret = []
|
ret = []
|
||||||
if not root:
|
if not root:
|
||||||
return []
|
return []
|
||||||
return in_order(root.left) + [root.value] + in_order(root.right)
|
return in_order(root.left) + [root.value] + in_order(root.right)
|
||||||
|
|
||||||
|
|
||||||
def height(root):
|
def height(root):
|
||||||
if not root:
|
if not root:
|
||||||
return 0
|
return 0
|
||||||
return 1 + max(height(root.left), height(root.right))
|
return 1 + max(height(root.left), height(root.right))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
pass
|
pass
|
||||||
|
@ -23,96 +23,187 @@ from .RangeDict import RangeDict
|
|||||||
# Register space Addresses is defined on the paragraph 6.3.2 of the following document: https://trustedcomputinggroup.org/wp-content/uploads/PC-Client-Specific-Platform-TPM-Profile-for-TPM-2p0-v1p05p_r14_pub.pdf
|
# Register space Addresses is defined on the paragraph 6.3.2 of the following document: https://trustedcomputinggroup.org/wp-content/uploads/PC-Client-Specific-Platform-TPM-Profile-for-TPM-2p0-v1p05p_r14_pub.pdf
|
||||||
# Credit: https://github.com/FSecureLABS/bitlocker-spi-toolkit
|
# Credit: https://github.com/FSecureLABS/bitlocker-spi-toolkit
|
||||||
|
|
||||||
fifo_registers = RangeDict()
|
# TPM 2.0 registers
|
||||||
fifo_registers[(0x0000, 0x0000)] = "TPM_ACCESS_0"
|
fifo_registers2 = RangeDict()
|
||||||
fifo_registers[(0x0001, 0x0007)] = "Reserved"
|
fifo_registers2[(0x0000, 0x0000)] = "TPM_ACCESS_0"
|
||||||
fifo_registers[(0x0008, 0x000b)] = "TPM_INT_ENABLE_0"
|
fifo_registers2[(0x0001, 0x0007)] = "Reserved"
|
||||||
fifo_registers[(0x000c, 0x000c)] = "TPM_INT_VECTOR_0"
|
fifo_registers2[(0x0008, 0x000b)] = "TPM_INT_ENABLE_0"
|
||||||
fifo_registers[(0x000d, 0x000f)] = "Reserved"
|
fifo_registers2[(0x000c, 0x000c)] = "TPM_INT_VECTOR_0"
|
||||||
fifo_registers[(0x0010, 0x0013)] = "TPM_INT_STATUS_0"
|
fifo_registers2[(0x000d, 0x000f)] = "Reserved"
|
||||||
fifo_registers[(0x0014, 0x0017)] = "TPM_INTF_CAPABILITY_0"
|
fifo_registers2[(0x0010, 0x0013)] = "TPM_INT_STATUS_0"
|
||||||
fifo_registers[(0x0018, 0x001b)] = "TPM_STS_0"
|
fifo_registers2[(0x0014, 0x0017)] = "TPM_INTF_CAPABILITY_0"
|
||||||
fifo_registers[(0x001c, 0x0023)] = "Reserved"
|
fifo_registers2[(0x0018, 0x001b)] = "TPM_STS_0"
|
||||||
fifo_registers[(0x0024, 0x0027)] = "TPM_DATA_FIFO_0"
|
fifo_registers2[(0x001c, 0x0023)] = "Reserved"
|
||||||
fifo_registers[(0x0028, 0x002f)] = "Reserved"
|
fifo_registers2[(0x0024, 0x0027)] = "TPM_DATA_FIFO_0"
|
||||||
fifo_registers[(0x0030, 0x0033)] = "TPM_INTERFACE_ID_0"
|
fifo_registers2[(0x0028, 0x002f)] = "Reserved"
|
||||||
fifo_registers[(0x0034, 0x007f)] = "Reserved"
|
fifo_registers2[(0x0030, 0x0033)] = "TPM_INTERFACE_ID_0"
|
||||||
fifo_registers[(0x0080, 0x0083)] = "TPM_XDATA_FIFO_0"
|
fifo_registers2[(0x0034, 0x007f)] = "Reserved"
|
||||||
fifo_registers[(0x0084, 0x0881)] = "Reserved"
|
fifo_registers2[(0x0080, 0x0083)] = "TPM_XDATA_FIFO_0"
|
||||||
fifo_registers[(0x0f00, 0x0f03)] = "TPM_DID_VID_0"
|
fifo_registers2[(0x0084, 0x0881)] = "Reserved"
|
||||||
fifo_registers[(0x0f04, 0x0f04)] = "TPM_RID_0"
|
fifo_registers2[(0x0f00, 0x0f03)] = "TPM_DID_VID_0"
|
||||||
fifo_registers[(0x0f90, 0x0fff)] = "Reserved"
|
fifo_registers2[(0x0f04, 0x0f04)] = "TPM_RID_0"
|
||||||
fifo_registers[(0x1000, 0x1000)] = "TPM_ACCESS_1"
|
fifo_registers2[(0x0f90, 0x0fff)] = "Reserved"
|
||||||
fifo_registers[(0x1001, 0x1007)] = "Reserved"
|
fifo_registers2[(0x1000, 0x1000)] = "TPM_ACCESS_1"
|
||||||
fifo_registers[(0x1008, 0x100b)] = "TPM_INT_ENABLE_1"
|
fifo_registers2[(0x1001, 0x1007)] = "Reserved"
|
||||||
fifo_registers[(0x100c, 0x100c)] = "TPM_INT_VECTOR_1"
|
fifo_registers2[(0x1008, 0x100b)] = "TPM_INT_ENABLE_1"
|
||||||
fifo_registers[(0x100d, 0x100f)] = "Reserved"
|
fifo_registers2[(0x100c, 0x100c)] = "TPM_INT_VECTOR_1"
|
||||||
fifo_registers[(0x1010, 0x1013)] = "TPM_INT_STATUS_1"
|
fifo_registers2[(0x100d, 0x100f)] = "Reserved"
|
||||||
fifo_registers[(0x1014, 0x1017)] = "TPM_INTF_CAPABILITY_1"
|
fifo_registers2[(0x1010, 0x1013)] = "TPM_INT_STATUS_1"
|
||||||
fifo_registers[(0x1018, 0x101b)] = "TPM_STS_1"
|
fifo_registers2[(0x1014, 0x1017)] = "TPM_INTF_CAPABILITY_1"
|
||||||
fifo_registers[(0x101c, 0x1023)] = "Reserved"
|
fifo_registers2[(0x1018, 0x101b)] = "TPM_STS_1"
|
||||||
fifo_registers[(0x1024, 0x1027)] = "TPM_DATA_FIFO_1"
|
fifo_registers2[(0x101c, 0x1023)] = "Reserved"
|
||||||
fifo_registers[(0x1028, 0x102f)] = "Reserved"
|
fifo_registers2[(0x1024, 0x1027)] = "TPM_DATA_FIFO_1"
|
||||||
fifo_registers[(0x1030, 0x1030)] = "TPM_INTERFACE_ID_1"
|
fifo_registers2[(0x1028, 0x102f)] = "Reserved"
|
||||||
fifo_registers[(0x1037, 0x107f)] = "Reserved"
|
fifo_registers2[(0x1030, 0x1030)] = "TPM_INTERFACE_ID_1"
|
||||||
fifo_registers[(0x1080, 0x1083)] = "TPM_XDATA_FIFO_1"
|
fifo_registers2[(0x1037, 0x107f)] = "Reserved"
|
||||||
fifo_registers[(0x1084, 0x1eff)] = "Reserved"
|
fifo_registers2[(0x1080, 0x1083)] = "TPM_XDATA_FIFO_1"
|
||||||
fifo_registers[(0x1f00, 0x1f03)] = "TPM_DID_VID_1"
|
fifo_registers2[(0x1084, 0x1eff)] = "Reserved"
|
||||||
fifo_registers[(0x1f04, 0x1f04)] = "TPM_RID_1"
|
fifo_registers2[(0x1f00, 0x1f03)] = "TPM_DID_VID_1"
|
||||||
fifo_registers[(0x1f05, 0x1fff)] = "Reserved"
|
fifo_registers2[(0x1f04, 0x1f04)] = "TPM_RID_1"
|
||||||
fifo_registers[(0x2000, 0x2000)] = "TPM_ACCESS_2"
|
fifo_registers2[(0x1f05, 0x1fff)] = "Reserved"
|
||||||
fifo_registers[(0x2001, 0x2007)] = "Reserved"
|
fifo_registers2[(0x2000, 0x2000)] = "TPM_ACCESS_2"
|
||||||
fifo_registers[(0x2008, 0x200b)] = "TPM_INT_ENABLE_2"
|
fifo_registers2[(0x2001, 0x2007)] = "Reserved"
|
||||||
fifo_registers[(0x200c, 0x200c)] = "TPM_INT_VECTOR_2"
|
fifo_registers2[(0x2008, 0x200b)] = "TPM_INT_ENABLE_2"
|
||||||
fifo_registers[(0x200d, 0x200f)] = "Reserved"
|
fifo_registers2[(0x200c, 0x200c)] = "TPM_INT_VECTOR_2"
|
||||||
fifo_registers[(0x2010, 0x2013)] = "TPM_INT_STATUS_2"
|
fifo_registers2[(0x200d, 0x200f)] = "Reserved"
|
||||||
fifo_registers[(0x2014, 0x2017)] = "TPM_INTF_CAPABILITY_2"
|
fifo_registers2[(0x2010, 0x2013)] = "TPM_INT_STATUS_2"
|
||||||
fifo_registers[(0x2018, 0x201b)] = "TPM_STS_2"
|
fifo_registers2[(0x2014, 0x2017)] = "TPM_INTF_CAPABILITY_2"
|
||||||
fifo_registers[(0x201c, 0x2023)] = "Reserved"
|
fifo_registers2[(0x2018, 0x201b)] = "TPM_STS_2"
|
||||||
fifo_registers[(0x2024, 0x2027)] = "TPM_DATA_FIFO_2"
|
fifo_registers2[(0x201c, 0x2023)] = "Reserved"
|
||||||
fifo_registers[(0x2028, 0x202f)] = "Reserved"
|
fifo_registers2[(0x2024, 0x2027)] = "TPM_DATA_FIFO_2"
|
||||||
fifo_registers[(0x2030, 0x2033)] = "TPM_INTERFACE_ID_2"
|
fifo_registers2[(0x2028, 0x202f)] = "Reserved"
|
||||||
fifo_registers[(0x2034, 0x207f)] = "Reserved"
|
fifo_registers2[(0x2030, 0x2033)] = "TPM_INTERFACE_ID_2"
|
||||||
fifo_registers[(0x2080, 0x2083)] = "TPM_XDATA_FIFO_2"
|
fifo_registers2[(0x2034, 0x207f)] = "Reserved"
|
||||||
fifo_registers[(0x2084, 0x2eff)] = "Reserved"
|
fifo_registers2[(0x2080, 0x2083)] = "TPM_XDATA_FIFO_2"
|
||||||
fifo_registers[(0x2f00, 0x2f03)] = "TPM_DID_VID_2"
|
fifo_registers2[(0x2084, 0x2eff)] = "Reserved"
|
||||||
fifo_registers[(0x2f04, 0x2f04)] = "TPM_RID_2"
|
fifo_registers2[(0x2f00, 0x2f03)] = "TPM_DID_VID_2"
|
||||||
fifo_registers[(0x2f05, 0x2fff)] = "Reserved"
|
fifo_registers2[(0x2f04, 0x2f04)] = "TPM_RID_2"
|
||||||
fifo_registers[(0x3000, 0x3000)] = "TPM_ACCESS_3"
|
fifo_registers2[(0x2f05, 0x2fff)] = "Reserved"
|
||||||
fifo_registers[(0x3001, 0x3007)] = "Reserved"
|
fifo_registers2[(0x3000, 0x3000)] = "TPM_ACCESS_3"
|
||||||
fifo_registers[(0x3008, 0x300b)] = "TPM_INT_ENABLE_3"
|
fifo_registers2[(0x3001, 0x3007)] = "Reserved"
|
||||||
fifo_registers[(0x300c, 0x300c)] = "TPM_INT_VECTOR_3"
|
fifo_registers2[(0x3008, 0x300b)] = "TPM_INT_ENABLE_3"
|
||||||
fifo_registers[(0x300d, 0x300f)] = "Reserved"
|
fifo_registers2[(0x300c, 0x300c)] = "TPM_INT_VECTOR_3"
|
||||||
fifo_registers[(0x3010, 0x3013)] = "TPM_INT_STATUS_3"
|
fifo_registers2[(0x300d, 0x300f)] = "Reserved"
|
||||||
fifo_registers[(0x3014, 0x3017)] = "TPM_INTF_CAPABILITY_3"
|
fifo_registers2[(0x3010, 0x3013)] = "TPM_INT_STATUS_3"
|
||||||
fifo_registers[(0x3018, 0x301b)] = "TPM_STS_3"
|
fifo_registers2[(0x3014, 0x3017)] = "TPM_INTF_CAPABILITY_3"
|
||||||
fifo_registers[(0x301c, 0x3023)] = "Reserved"
|
fifo_registers2[(0x3018, 0x301b)] = "TPM_STS_3"
|
||||||
fifo_registers[(0x3024, 0x3027)] = "TPM_DATA_FIFO_3"
|
fifo_registers2[(0x301c, 0x3023)] = "Reserved"
|
||||||
fifo_registers[(0x3028, 0x302f)] = "Reserved"
|
fifo_registers2[(0x3024, 0x3027)] = "TPM_DATA_FIFO_3"
|
||||||
fifo_registers[(0x3030, 0x3033)] = "TPM_INTERFACE_ID_3"
|
fifo_registers2[(0x3028, 0x302f)] = "Reserved"
|
||||||
fifo_registers[(0x3034, 0x307f)] = "Reserved"
|
fifo_registers2[(0x3030, 0x3033)] = "TPM_INTERFACE_ID_3"
|
||||||
fifo_registers[(0x3080, 0x3083)] = "TPM_XDATA_FIFO_3"
|
fifo_registers2[(0x3034, 0x307f)] = "Reserved"
|
||||||
fifo_registers[(0x3084, 0x3eff)] = "Reserved"
|
fifo_registers2[(0x3080, 0x3083)] = "TPM_XDATA_FIFO_3"
|
||||||
fifo_registers[(0x3f00, 0x3f03)] = "TPM_DID_VID_3"
|
fifo_registers2[(0x3084, 0x3eff)] = "Reserved"
|
||||||
fifo_registers[(0x3f04, 0x3f04)] = "TPM_RID_3"
|
fifo_registers2[(0x3f00, 0x3f03)] = "TPM_DID_VID_3"
|
||||||
fifo_registers[(0x3f05, 0x3fff)] = "Reserved"
|
fifo_registers2[(0x3f04, 0x3f04)] = "TPM_RID_3"
|
||||||
fifo_registers[(0x4000, 0x4000)] = "TPM_ACCESS_4"
|
fifo_registers2[(0x3f05, 0x3fff)] = "Reserved"
|
||||||
fifo_registers[(0x4001, 0x4007)] = "Reserved"
|
fifo_registers2[(0x4000, 0x4000)] = "TPM_ACCESS_4"
|
||||||
fifo_registers[(0x4008, 0x400b)] = "TPM_INT_ENABLE_4"
|
fifo_registers2[(0x4001, 0x4007)] = "Reserved"
|
||||||
fifo_registers[(0x400c, 0x400c)] = "TPM_INT_VECTOR_4"
|
fifo_registers2[(0x4008, 0x400b)] = "TPM_INT_ENABLE_4"
|
||||||
fifo_registers[(0x400d, 0x400f)] = "Reserved"
|
fifo_registers2[(0x400c, 0x400c)] = "TPM_INT_VECTOR_4"
|
||||||
fifo_registers[(0x4010, 0x4013)] = "TPM_INT_STATUS_4"
|
fifo_registers2[(0x400d, 0x400f)] = "Reserved"
|
||||||
fifo_registers[(0x4014, 0x4017)] = "TPM_INTF_CAPABILITY_4"
|
fifo_registers2[(0x4010, 0x4013)] = "TPM_INT_STATUS_4"
|
||||||
fifo_registers[(0x4018, 0x401b)] = "TPM_STS_4"
|
fifo_registers2[(0x4014, 0x4017)] = "TPM_INTF_CAPABILITY_4"
|
||||||
fifo_registers[(0x401c, 0x401f)] = "Reserved"
|
fifo_registers2[(0x4018, 0x401b)] = "TPM_STS_4"
|
||||||
fifo_registers[(0x4020, 0x4023)] = "TPM_HASH_END"
|
fifo_registers2[(0x401c, 0x401f)] = "Reserved"
|
||||||
fifo_registers[(0x4024, 0x4027)] = "TPM_DATA_FIFO_4"
|
fifo_registers2[(0x4020, 0x4023)] = "TPM_HASH_END"
|
||||||
fifo_registers[(0x4028, 0x402f)] = "TPM_HASH_START"
|
fifo_registers2[(0x4024, 0x4027)] = "TPM_DATA_FIFO_4"
|
||||||
fifo_registers[(0x4030, 0x4033)] = "TPM_INTERFACE_ID_4"
|
fifo_registers2[(0x4028, 0x402f)] = "TPM_HASH_START"
|
||||||
fifo_registers[(0x4034, 0x407f)] = "Reserved"
|
fifo_registers2[(0x4030, 0x4033)] = "TPM_INTERFACE_ID_4"
|
||||||
fifo_registers[(0x4080, 0x4083)] = "TPM_XDATA_FIFO_4"
|
fifo_registers2[(0x4034, 0x407f)] = "Reserved"
|
||||||
fifo_registers[(0x4084, 0x4eff)] = "Reserved"
|
fifo_registers2[(0x4080, 0x4083)] = "TPM_XDATA_FIFO_4"
|
||||||
fifo_registers[(0x4f00, 0x4f03)] = "TPM_DID_VID_4"
|
fifo_registers2[(0x4084, 0x4eff)] = "Reserved"
|
||||||
fifo_registers[(0x4f04, 0x4f04)] = "TPM_RID_4"
|
fifo_registers2[(0x4f00, 0x4f03)] = "TPM_DID_VID_4"
|
||||||
fifo_registers[(0x4f05, 0x4fff)] = "Reserved"
|
fifo_registers2[(0x4f04, 0x4f04)] = "TPM_RID_4"
|
||||||
fifo_registers[(0x5000, 0x5fff)] = "Reserved"
|
fifo_registers2[(0x4f05, 0x4fff)] = "Reserved"
|
||||||
|
fifo_registers2[(0x5000, 0x5fff)] = "Reserved"
|
||||||
|
|
||||||
|
# TPM 1.2 registers
|
||||||
|
fifo_registers1 = RangeDict()
|
||||||
|
fifo_registers1[(0x0000, 0x0000)] = "TPM_ACCESS_0"
|
||||||
|
fifo_registers1[(0x0008, 0x000b)] = "TPM_INT_ENABLE_0"
|
||||||
|
fifo_registers1[(0x000c, 0x000c)] = "TPM_INT_VECTOR_0"
|
||||||
|
fifo_registers1[(0x0010, 0x0013)] = "TPM_INT_STATUS_0"
|
||||||
|
fifo_registers1[(0x0014, 0x0017)] = "TPM_INTF_CAPABILITY_0"
|
||||||
|
fifo_registers1[(0x0018, 0x001a)] = "TPM_STS_0"
|
||||||
|
fifo_registers1[(0x0024, 0x0027)] = "TPM_DATA_FIFO_0"
|
||||||
|
fifo_registers1[(0x0080, 0x0083)] = "TPM_XDATA_FIFO_0"
|
||||||
|
fifo_registers1[(0x0084, 0x00bf)] = "Reserved"
|
||||||
|
fifo_registers1[(0x0f00, 0x0f03)] = "TPM_DID_VID_0"
|
||||||
|
fifo_registers1[(0x0f04, 0x0f04)] = "TPM_RID_0"
|
||||||
|
fifo_registers1[(0x0f05, 0x0f7f)] = "Reserved"
|
||||||
|
fifo_registers1[(0x0f80, 0x0f80)] = "FIRST_LEGACY_ADDRESS_0"
|
||||||
|
fifo_registers1[(0x0f84, 0x0f84)] = "FIRST_LEGACY_ADDRESS_EXTENSION_0"
|
||||||
|
fifo_registers1[(0x0f88, 0x0f88)] = "SECOND_LEGACY_ADDRESS_0"
|
||||||
|
fifo_registers1[(0x0f8c, 0x0f8c)] = "SECOND_LEGACY_ADDRESS_EXTENSION_0"
|
||||||
|
fifo_registers1[(0x0f90, 0x0fff)] = "VENDOR_DEFINED"
|
||||||
|
fifo_registers1[(0x1000, 0x1000)] = "TPM_ACCESS_1"
|
||||||
|
fifo_registers1[(0x1008, 0x100b)] = "TPM_INT_ENABLE_1"
|
||||||
|
fifo_registers1[(0x100c, 0x100c)] = "TPM_INT_VECTOR_1"
|
||||||
|
fifo_registers1[(0x1010, 0x1013)] = "TPM_INT_STATUS_1"
|
||||||
|
fifo_registers1[(0x1014, 0x1017)] = "TPM_INTF_CAPABILITY_1"
|
||||||
|
fifo_registers1[(0x1018, 0x101a)] = "TPM_STS_1"
|
||||||
|
fifo_registers1[(0x1024, 0x1027)] = "TPM_DATA_FIFO_1"
|
||||||
|
fifo_registers1[(0x1080, 0x1083)] = "TPM_XDATA_FIFO_1"
|
||||||
|
fifo_registers1[(0x1084, 0x10bf)] = "Reserved"
|
||||||
|
fifo_registers1[(0x1f00, 0x1f03)] = "TPM_DID_VID_1"
|
||||||
|
fifo_registers1[(0x1f04, 0x1f04)] = "TPM_RID_1"
|
||||||
|
fifo_registers1[(0x1f05, 0x1f7f)] = "Reserved"
|
||||||
|
fifo_registers1[(0x1f80, 0x1f80)] = "Reserved"
|
||||||
|
fifo_registers1[(0x1f84, 0x1f84)] = "Reserved"
|
||||||
|
fifo_registers1[(0x1f88, 0x1f88)] = "Reserved"
|
||||||
|
fifo_registers1[(0x1f8c, 0x1f8c)] = "Reserved"
|
||||||
|
fifo_registers1[(0x1f90, 0x1fff)] = "VENDOR_DEFINED"
|
||||||
|
fifo_registers1[(0x2000, 0x2000)] = "TPM_ACCESS_2"
|
||||||
|
fifo_registers1[(0x2008, 0x200b)] = "TPM_INT_ENABLE_2"
|
||||||
|
fifo_registers1[(0x200c, 0x200c)] = "TPM_INT_VECTOR_2"
|
||||||
|
fifo_registers1[(0x2010, 0x2013)] = "TPM_INT_STATUS_2"
|
||||||
|
fifo_registers1[(0x2014, 0x2017)] = "TPM_INTF_CAPABILITY_2"
|
||||||
|
fifo_registers1[(0x2018, 0x201a)] = "TPM_STS_2"
|
||||||
|
fifo_registers1[(0x2024, 0x2027)] = "TPM_DATA_FIFO_2"
|
||||||
|
fifo_registers1[(0x2080, 0x2083)] = "TPM_XDATA_FIFO_2"
|
||||||
|
fifo_registers1[(0x2084, 0x20bf)] = "Reserved"
|
||||||
|
fifo_registers1[(0x2f00, 0x2f03)] = "TPM_DID_VID_2"
|
||||||
|
fifo_registers1[(0x2f04, 0x2f04)] = "TPM_RID_2"
|
||||||
|
fifo_registers1[(0x2f05, 0x2f7f)] = "Reserved"
|
||||||
|
fifo_registers1[(0x2f80, 0x2f80)] = "Reserved"
|
||||||
|
fifo_registers1[(0x2f84, 0x2f84)] = "Reserved"
|
||||||
|
fifo_registers1[(0x2f88, 0x2f88)] = "Reserved"
|
||||||
|
fifo_registers1[(0x2f8c, 0x2f8c)] = "Reserved"
|
||||||
|
fifo_registers1[(0x2f90, 0x2fff)] = "VENDOR_DEFINED"
|
||||||
|
fifo_registers1[(0x3000, 0x3000)] = "TPM_ACCESS_3"
|
||||||
|
fifo_registers1[(0x3008, 0x300b)] = "TPM_INT_ENABLE_3"
|
||||||
|
fifo_registers1[(0x300c, 0x300c)] = "TPM_INT_VECTOR_3"
|
||||||
|
fifo_registers1[(0x3010, 0x3013)] = "TPM_INT_STATUS_3"
|
||||||
|
fifo_registers1[(0x3014, 0x3017)] = "TPM_INTF_CAPABILITY_3"
|
||||||
|
fifo_registers1[(0x3018, 0x301a)] = "TPM_STS_3"
|
||||||
|
fifo_registers1[(0x3024, 0x3027)] = "TPM_DATA_FIFO_3"
|
||||||
|
fifo_registers1[(0x3080, 0x3083)] = "TPM_XDATA_FIFO_3"
|
||||||
|
fifo_registers1[(0x3084, 0x30bf)] = "Reserved"
|
||||||
|
fifo_registers1[(0x3f00, 0x3f03)] = "TPM_DID_VID_3"
|
||||||
|
fifo_registers1[(0x3f04, 0x3f04)] = "TPM_RID_3"
|
||||||
|
fifo_registers1[(0x3f05, 0x3f7f)] = "Reserved"
|
||||||
|
fifo_registers1[(0x3f80, 0x3f80)] = "Reserved"
|
||||||
|
fifo_registers1[(0x3f84, 0x3f84)] = "Reserved"
|
||||||
|
fifo_registers1[(0x3f88, 0x3f88)] = "Reserved"
|
||||||
|
fifo_registers1[(0x3f8c, 0x3f8c)] = "Reserved"
|
||||||
|
fifo_registers1[(0x3f90, 0x3fff)] = "VENDOR_DEFINED"
|
||||||
|
fifo_registers1[(0x4000, 0x4000)] = "TPM_ACCESS_4"
|
||||||
|
fifo_registers1[(0x4008, 0x400b)] = "TPM_INT_ENABLE_4"
|
||||||
|
fifo_registers1[(0x400c, 0x400c)] = "TPM_INT_VECTOR_4"
|
||||||
|
fifo_registers1[(0x4010, 0x4013)] = "TPM_INT_STATUS_4"
|
||||||
|
fifo_registers1[(0x4014, 0x4017)] = "TPM_INTF_CAPABILITY_4"
|
||||||
|
fifo_registers1[(0x4018, 0x401a)] = "TPM_STS_4"
|
||||||
|
fifo_registers1[(0x4020, 0x4020)] = "TPM_HASH_END"
|
||||||
|
fifo_registers1[(0x4024, 0x4027)] = "TPM_DATA_FIFO_4"
|
||||||
|
fifo_registers1[(0x4028, 0x4028)] = "TPM_HASH_START"
|
||||||
|
fifo_registers1[(0x4080, 0x4083)] = "TPM_XDATA_FIFO_4"
|
||||||
|
fifo_registers1[(0x4084, 0x40bf)] = "Reserved"
|
||||||
|
fifo_registers1[(0x4f00, 0x4f03)] = "TPM_DID_VID_4"
|
||||||
|
fifo_registers1[(0x4f04, 0x4f04)] = "TPM_RID_4"
|
||||||
|
fifo_registers1[(0x4f05, 0x4f7f)] = "Reserved"
|
||||||
|
fifo_registers1[(0x4f80, 0x4f80)] = "Reserved"
|
||||||
|
fifo_registers1[(0x4f84, 0x4f84)] = "Reserved"
|
||||||
|
fifo_registers1[(0x4f88, 0x4f88)] = "Reserved"
|
||||||
|
fifo_registers1[(0x4f8c, 0x4f8c)] = "Reserved"
|
||||||
|
fifo_registers1[(0x4f90, 0x4fff)] = "VENDOR_DEFINED"
|
||||||
|
@ -20,12 +20,12 @@
|
|||||||
import sigrokdecode as srd
|
import sigrokdecode as srd
|
||||||
import re
|
import re
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from .lists import fifo_registers
|
from .lists import fifo_registers2, fifo_registers1
|
||||||
|
|
||||||
|
|
||||||
class Ann:
|
class Ann:
|
||||||
""" Annotation ID """
|
""" Annotation ID """
|
||||||
READ, WRITE, ADDRESS, DATA, VMK = range(5)
|
READ, WRITE, ADDRESS, WAIT, DATA, VMK = range(6)
|
||||||
|
|
||||||
|
|
||||||
class Operation:
|
class Operation:
|
||||||
@ -64,6 +64,7 @@ class Transaction:
|
|||||||
self.end_sample_op = None
|
self.end_sample_op = None
|
||||||
self.end_sample_addr = None
|
self.end_sample_addr = None
|
||||||
self.end_sample_data = None
|
self.end_sample_data = None
|
||||||
|
self.end_sample_wait = None
|
||||||
self.operation = operation
|
self.operation = operation
|
||||||
self.address = bytearray()
|
self.address = bytearray()
|
||||||
self.data = bytearray()
|
self.data = bytearray()
|
||||||
@ -85,7 +86,7 @@ class Transaction:
|
|||||||
""" Check if all address bytes are captured. """
|
""" Check if all address bytes are captured. """
|
||||||
return len(self.address) == 3
|
return len(self.address) == 3
|
||||||
|
|
||||||
def frame(self):
|
def frame(self, fifo_registers):
|
||||||
""" Return address and data annotation if the transaction is complete. """
|
""" Return address and data annotation if the transaction is complete. """
|
||||||
if self.is_complete():
|
if self.is_complete():
|
||||||
register_name = ""
|
register_name = ""
|
||||||
@ -93,14 +94,20 @@ class Transaction:
|
|||||||
register_name = fifo_registers[int.from_bytes(self.address, "big") & 0xffff]
|
register_name = fifo_registers[int.from_bytes(self.address, "big") & 0xffff]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
register_name = "Unknown"
|
register_name = "Unknown"
|
||||||
wait_str = '' if self.wait_count == 0 else ' (Waits: {})'.format(self.wait_count)
|
|
||||||
data_str = ''.join('{:02x}'.format(x) for x in self.data)
|
data_str = ''.join('{:02x}'.format(x) for x in self.data)
|
||||||
op_ann = ['Read', 'Rd'] if self.operation == Operation.READ else ['Write', 'Wr']
|
op_ann = ['Read', 'Rd'] if self.operation == Operation.READ else ['Write', 'Wr']
|
||||||
|
wait_ann = ['Wait', 'Wt']
|
||||||
addr_ann = ['Register: {}'.format(register_name), '{}'.format(register_name)]
|
addr_ann = ['Register: {}'.format(register_name), '{}'.format(register_name)]
|
||||||
data_ann = ['{}{}'.format(data_str, wait_str), '{}'.format(data_str), data_str]
|
data_ann = ['{}'.format(data_str), '{}'.format(data_str), data_str]
|
||||||
return ((self.start_sample, self.end_sample_op, op_ann),
|
if self.wait_count > 0:
|
||||||
(self.end_sample_op, self.end_sample_addr, addr_ann),
|
return ((self.start_sample, self.end_sample_op, op_ann),
|
||||||
(self.end_sample_addr, self.end_sample_data, data_ann))
|
(self.end_sample_op, self.end_sample_addr, addr_ann),
|
||||||
|
(self.end_sample_addr, self.end_sample_wait, wait_ann),
|
||||||
|
(self.end_sample_wait, self.end_sample_data, data_ann))
|
||||||
|
else:
|
||||||
|
return ((self.start_sample, self.end_sample_op, op_ann),
|
||||||
|
(self.end_sample_op, self.end_sample_addr, addr_ann),
|
||||||
|
(self.end_sample_addr, self.end_sample_data, data_ann))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@ -119,18 +126,20 @@ class Decoder(srd.Decoder):
|
|||||||
('Write', 'Write register operation'),
|
('Write', 'Write register operation'),
|
||||||
('Address', 'Register address'),
|
('Address', 'Register address'),
|
||||||
('Data', 'Data'),
|
('Data', 'Data'),
|
||||||
|
('Wait', 'Wait'),
|
||||||
('VMK', 'Extracted BitLocker VMK'),
|
('VMK', 'Extracted BitLocker VMK'),
|
||||||
)
|
)
|
||||||
annotation_rows = (
|
annotation_rows = (
|
||||||
('Transactions', 'TPM transactions', (0, 1, 2, 3)),
|
('Transactions', 'TPM transactions', (0, 1, 2, 3, 4)),
|
||||||
('B-VMK', 'BitLocker Volume Master Key', (4,)),
|
('B-VMK', 'BitLocker Volume Master Key', (5,)),
|
||||||
)
|
)
|
||||||
options = (
|
options = (
|
||||||
{'id': 'wait_mask', 'desc': 'TPM Wait transfer Mask', 'default': '0x00',
|
{'id': 'tpm_version', 'desc': 'TPM Version 1.2 or 2.0', 'default': '2.0',
|
||||||
'values': ('0x00', '0xFE')},
|
'values': ('2.0', '1.2')},
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
# TPM Profile Specification for TPM 2.0 page 133-134
|
||||||
self.end_wait = 0x01
|
self.end_wait = 0x01
|
||||||
self.operation_mask = 0x80
|
self.operation_mask = 0x80
|
||||||
self.address_mask = 0x3f
|
self.address_mask = 0x3f
|
||||||
@ -142,6 +151,7 @@ class Decoder(srd.Decoder):
|
|||||||
self.reset()
|
self.reset()
|
||||||
self.state_machine = None
|
self.state_machine = None
|
||||||
self.init_state_machine()
|
self.init_state_machine()
|
||||||
|
self.fifo_registers = None
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
self.ss = self.es = 0
|
self.ss = self.es = 0
|
||||||
@ -153,6 +163,12 @@ class Decoder(srd.Decoder):
|
|||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
self.out_ann = self.register(srd.OUTPUT_ANN)
|
self.out_ann = self.register(srd.OUTPUT_ANN)
|
||||||
|
if self.options['tpm_version'] == "2.0":
|
||||||
|
self.wait_mask = 0x00
|
||||||
|
self.fifo_registers = fifo_registers2
|
||||||
|
else:
|
||||||
|
self.wait_mask = 0xFE
|
||||||
|
self.fifo_registers = fifo_registers1
|
||||||
|
|
||||||
def init_state_machine(self):
|
def init_state_machine(self):
|
||||||
self.state_machine = {
|
self.state_machine = {
|
||||||
@ -178,7 +194,9 @@ class Decoder(srd.Decoder):
|
|||||||
def _transaction_wait(self, mosi, miso):
|
def _transaction_wait(self, mosi, miso):
|
||||||
self.current_transaction.wait_count += 1
|
self.current_transaction.wait_count += 1
|
||||||
if miso == self.end_wait:
|
if miso == self.end_wait:
|
||||||
|
self.current_transaction.end_sample_wait = self.es
|
||||||
self.state = TransactionState.TRANSFER_DATA
|
self.state = TransactionState.TRANSFER_DATA
|
||||||
|
return
|
||||||
|
|
||||||
def _transaction_read(self, mosi, miso):
|
def _transaction_read(self, mosi, miso):
|
||||||
# TPM operation is defined on the 7th bit of the first byte of the transaction (1=read / 0=write)
|
# TPM operation is defined on the 7th bit of the first byte of the transaction (1=read / 0=write)
|
||||||
@ -200,32 +218,48 @@ class Decoder(srd.Decoder):
|
|||||||
# Get address bytes
|
# Get address bytes
|
||||||
# Address is 3 bytes long
|
# Address is 3 bytes long
|
||||||
self.current_transaction.address.extend(mosi.to_bytes(1, byteorder='big'))
|
self.current_transaction.address.extend(mosi.to_bytes(1, byteorder='big'))
|
||||||
# The transfer size byte is sent at the same time than the last byte address
|
|
||||||
if self.current_transaction.is_address_complete():
|
if self.current_transaction.is_address_complete():
|
||||||
self.current_transaction.end_sample_addr = self.es
|
self.current_transaction.end_sample_addr = self.es
|
||||||
self.state = TransactionState.TRANSFER_DATA
|
if miso == self.wait_mask:
|
||||||
|
self.state = TransactionState.WAIT
|
||||||
|
else:
|
||||||
|
self.state = TransactionState.TRANSFER_DATA
|
||||||
return
|
return
|
||||||
|
|
||||||
def _transaction_data(self, mosi, miso):
|
def _transaction_data(self, mosi, miso):
|
||||||
self.current_transaction.end_sample_data = self.es
|
self.current_transaction.end_sample_data = self.es
|
||||||
if miso == self.wait_mask:
|
|
||||||
self.state = TransactionState.WAIT
|
|
||||||
return
|
|
||||||
if self.current_transaction.operation == Operation.READ:
|
if self.current_transaction.operation == Operation.READ:
|
||||||
self.current_transaction.data.extend(miso.to_bytes(1, byteorder='big'))
|
self.current_transaction.data.extend(miso.to_bytes(1, byteorder='big'))
|
||||||
self.recover_vmk(miso)
|
self.recover_vmk(miso)
|
||||||
elif self.current_transaction.operation == Operation.WRITE:
|
elif self.current_transaction.operation == Operation.WRITE:
|
||||||
self.current_transaction.data.extend(mosi.to_bytes(1, byteorder='big'))
|
self.current_transaction.data.extend(mosi.to_bytes(1, byteorder='big'))
|
||||||
# Check if the transaction is complete
|
# Check if the transaction is complete
|
||||||
annotation = self.current_transaction.frame()
|
annotation = self.current_transaction.frame(self.fifo_registers)
|
||||||
if annotation:
|
if annotation:
|
||||||
(op_ss, op_es, op_ann), (addr_ss, addr_es, addr_ann), (data_ss, data_es, data_ann) = annotation
|
if self.current_transaction.wait_count == 0:
|
||||||
self.put(op_ss, op_es, self.out_ann,
|
(op_ss, op_es, op_ann), (addr_ss, addr_es, addr_ann), (data_ss, data_es, data_ann) = annotation
|
||||||
|
self.put(op_ss, op_es, self.out_ann,
|
||||||
[Ann.READ if self.current_transaction.operation == Operation.READ else Ann.WRITE, op_ann])
|
[Ann.READ if self.current_transaction.operation == Operation.READ else Ann.WRITE, op_ann])
|
||||||
self.put(addr_ss, addr_es, self.out_ann, [Ann.ADDRESS, addr_ann])
|
self.put(addr_ss, addr_es, self.out_ann, [Ann.ADDRESS, addr_ann])
|
||||||
self.put(data_ss, data_es, self.out_ann, [Ann.DATA, data_ann])
|
self.put(data_ss, data_es, self.out_ann, [Ann.DATA, data_ann])
|
||||||
|
else:
|
||||||
|
(op_ss, op_es, op_ann), (addr_ss, addr_es, addr_ann), (wait_ss, wait_es, wait_ann), (data_ss, data_es, data_ann) = annotation
|
||||||
|
self.put(op_ss, op_es, self.out_ann,
|
||||||
|
[Ann.READ if self.current_transaction.operation == Operation.READ else Ann.WRITE, op_ann])
|
||||||
|
self.put(addr_ss, addr_es, self.out_ann, [Ann.ADDRESS, addr_ann])
|
||||||
|
self.put(wait_ss, wait_es, self.out_ann, [Ann.WAIT, wait_ann])
|
||||||
|
self.put(data_ss, data_es, self.out_ann, [Ann.DATA, data_ann])
|
||||||
self.end_current_transaction()
|
self.end_current_transaction()
|
||||||
|
|
||||||
|
def _is_vmk_transaction(self):
|
||||||
|
try:
|
||||||
|
if self.fifo_registers[int.from_bytes(self.current_transaction.address, "big") & 0xffff] == "TPM_DATA_FIFO_0":
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
except KeyError:
|
||||||
|
return False
|
||||||
|
|
||||||
def check_vmk_header(self):
|
def check_vmk_header(self):
|
||||||
""" Check for VMK header """
|
""" Check for VMK header """
|
||||||
if self.queue[0] == 0x2c:
|
if self.queue[0] == 0x2c:
|
||||||
@ -239,25 +273,29 @@ class Decoder(srd.Decoder):
|
|||||||
""" Check if VMK is releasing """
|
""" Check if VMK is releasing """
|
||||||
if not self.saving_vmk:
|
if not self.saving_vmk:
|
||||||
# Add data to the circular buffer
|
# Add data to the circular buffer
|
||||||
self.queue.append(miso)
|
# Check if the transaction actually got the VMK.
|
||||||
# Add sample number to meta queue
|
# Sometimes, other TPM transactions occurs when recovering the VMK
|
||||||
self.vmk_meta["s_queue"].append(self.ss)
|
if self._is_vmk_transaction():
|
||||||
# Check if VMK header retrieved
|
self.queue.append(miso)
|
||||||
self.check_vmk_header()
|
# Add sample number to meta queue
|
||||||
|
self.vmk_meta["s_queue"].append(self.ss)
|
||||||
|
# Check if VMK header retrieved
|
||||||
|
self.check_vmk_header()
|
||||||
else:
|
else:
|
||||||
if len(self.vmk) == 0:
|
if len(self.vmk) == 0:
|
||||||
self.vmk_meta["vmk_ss"] = self.ss
|
self.vmk_meta["vmk_ss"] = self.ss
|
||||||
if len(self.vmk) < 32:
|
if len(self.vmk) < 32:
|
||||||
self.vmk.append(miso)
|
# Check if the transaction actually got the VMK.
|
||||||
self.vmk_meta["vmk_es"] = self.es
|
# Sometimes, other TPM transactions occurs when recovering the VMK
|
||||||
|
if self._is_vmk_transaction():
|
||||||
|
self.vmk.append(miso)
|
||||||
|
self.vmk_meta["vmk_es"] = self.es
|
||||||
else:
|
else:
|
||||||
self.saving_vmk = False
|
self.saving_vmk = False
|
||||||
self.put(self.vmk_meta["vmk_ss"], self.vmk_meta["vmk_es"], self.out_ann,
|
self.put(self.vmk_meta["vmk_ss"], self.vmk_meta["vmk_es"], self.out_ann,
|
||||||
[Ann.VMK, ['VMK: {}'.format(''.join('{:02x}'.format(x) for x in self.vmk))]])
|
[Ann.VMK, ['VMK: {}'.format(''.join('{:02x}'.format(x) for x in self.vmk))]])
|
||||||
|
|
||||||
def decode(self, ss, es, data):
|
def decode(self, ss, es, data):
|
||||||
self.wait_mask = bytes.fromhex(self.options['wait_mask'].strip("0x"))
|
|
||||||
|
|
||||||
self.ss, self.es = ss, es
|
self.ss, self.es = ss, es
|
||||||
|
|
||||||
ptype, mosi, miso = data
|
ptype, mosi, miso = data
|
||||||
|
Loading…
x
Reference in New Issue
Block a user