Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions .github/workflows/build_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# QEMU OpenTitan CI
#
# Copyright (c) 2023-2025 Rivos, Inc.
# Copyright (c) 2025 lowRISC contributors.
# SPDX-License-Identifier: Apache License 2.0
#------------------------------------------------------------------------------

Expand Down Expand Up @@ -86,18 +87,20 @@ jobs:
lint-python:
runs-on: ubuntu-latest
steps:
- name: Check out QEMU
uses: actions/checkout@v4
- name: Install tools
run: |
sudo apt-get update &&
sudo apt-get install -y python3-pip
# ubuntu "latest" is too old to require --break-system-packages ...
pip3 install pylint==3.3.3
- name: Check out QEMU
uses: actions/checkout@v4
pip3 install -r scripts/opentitan/requirements.txt
- name: Lint Python code
run: |
flake8 --config scripts/opentitan/.flake8 scripts/opentitan/*.py \
python/qemu/jtagtools python/qemu/ot
pylint --rcfile scripts/opentitan/.pylintrc -d 'duplicate-code' -d 'fixme' \
scripts/opentitan/*.py python/qemu/jtagtools python/qemu/ot
scripts/opentitan/*.py python/qemu/jtagtools python/qemu/ot

lint-clang:
runs-on: ubuntu-24.04
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pylint-ot:
python-ot:
tags:
- qemu_ot
stage: build
Expand All @@ -9,4 +9,6 @@ pylint-ot:
- . .venv/bin/activate
- pip3 install -r scripts/opentitan/requirements.txt
- pylint --rcfile scripts/opentitan/.pylintrc -d 'duplicate-code' -d 'fixme'
scripts/opentitan/*.py python/qemu/jtagtools python/qemu/ot
scripts/opentitan/*.py python/qemu/jtagtools python/qemu/ot
- flake8 --config scripts/opentitan/.flake8
scripts/opentitan/*.py python/qemu/jtagtools python/qemu/ot
2 changes: 1 addition & 1 deletion .gitlab-ci.d/opentitan/qemu-ot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ variables:

include:
- local: '/.gitlab-ci.d/opentitan/build.yml'
- local: '/.gitlab-ci.d/opentitan/pylint-ot.yml'
- local: '/.gitlab-ci.d/opentitan/python-ot.yml'
- local: '/.gitlab-ci.d/opentitan/ot-smoke.yml'
- local: '/.gitlab-ci.d/opentitan/ot-bmtests.yml'
7 changes: 4 additions & 3 deletions python/qemu/jtagtools/jtag/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# Copyright (c) 2024 Rivos Inc. Emmanuel Blot <eblot@rivosinc.com>
# Copyright (c) 2010-2024, Emmanuel Blot <emmanuel.blot@free.fr>
# Copyright (c) 2025 lowRISC contributors.
# All rights reserved.
#
# SPDX-License-Identifier: Apache2

"""JTAG Tools."""

from .controller import JtagController
from .engine import JtagEngine
from .error import JtagError
from .controller import JtagController # noqa: F401
from .engine import JtagEngine # noqa: F401
from .error import JtagError # noqa: F401
2 changes: 2 additions & 0 deletions python/qemu/jtagtools/jtag/error.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# Copyright (c) 2024 Rivos Inc. Emmanuel Blot <eblot@rivosinc.com>
# Copyright (c) 2010-2024, Emmanuel Blot <emmanuel.blot@free.fr>
# Copyright (c) 2025 lowRISC contributors.
# All rights reserved.
#
# SPDX-License-Identifier: Apache2

"""JTAG Errors"""


class JtagError(Exception):
"""Generic JTAG error."""

Expand Down
3 changes: 2 additions & 1 deletion python/qemu/jtagtools/rbb/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# Copyright (c) 2024 Rivos Inc. Emmanuel Blot <eblot@rivosinc.com>
# Copyright (c) 2025 lowRISC contributors.
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause

"""JTAG Remote BitBang Controller"""

from .bitbang import JtagBitbangController
from .bitbang import JtagBitbangController # noqa: F401
3 changes: 2 additions & 1 deletion python/qemu/ot/devproxy.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) 2023-2025 Rivos, Inc.
# Copyright (c) 2025 lowRISC contributors.
# SPDX-License-Identifier: Apache2

"""Device proxy for OpenTitan devices and peripherals
Expand Down Expand Up @@ -1663,7 +1664,7 @@ def _receive(self):
continue
packet = bytes(buffer[:length])
self._log.debug('RX payload:%s%s', self.to_str(packet)[:80],
'...' if len(packet) > 80 else '')
'...' if len(packet) > 80 else '')
buffer = buffer[length:]
if resp:
if self._tx_uid != uid:
Expand Down
3 changes: 2 additions & 1 deletion python/qemu/ot/dtm/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# Copyright (c) 2024 Rivos, Inc.
# Copyright (c) 2025 lowRISC contributors.
# SPDX-License-Identifier: Apache2

"""Debug Module tools.

:author: Emmanuel Blot <eblot@rivosinc.com>
"""

from .dtm import DebugTransportModule
from .dtm import DebugTransportModule # noqa: F401
3 changes: 2 additions & 1 deletion python/qemu/ot/dtm/dtm.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) 2024 Rivos, Inc.
# Copyright (c) 2025 lowRISC contributors.
# SPDX-License-Identifier: Apache2

"""Debug Module tools.
Expand Down Expand Up @@ -214,7 +215,7 @@ def _build_dmi(self, address: int) -> int:
self._log.debug('DMI width: %d bits', self._abits)
if address >= (1 << self._abits):
raise ValueError(f'Address 0x{address:x} too large, '
f'max 0x{(1 << self._abits) -1:x}')
f'max 0x{(1 << self._abits) - 1:x}')
return address << (32 + 2)

def _check_error(self) -> None:
Expand Down
3 changes: 2 additions & 1 deletion python/qemu/ot/km/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Copyright (c) 2025 Rivos, Inc.
# Copyright (c) 2025 lowRISC contributors.
# SPDX-License-Identifier: Apache2

"""KeyManager tools."""

from .dpe import KeyManagerDpe
from .dpe import KeyManagerDpe # noqa: F401
3 changes: 2 additions & 1 deletion python/qemu/ot/km/dpe.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env python3

# Copyright (c) 2025 Rivos, Inc.
# Copyright (c) 2025 lowRISC contributors.
# SPDX-License-Identifier: Apache2

"""QEMU OT tool to generate Key Manager DPE keys.
Expand Down Expand Up @@ -100,7 +101,7 @@ def from_args(cls, args: Namespace) -> 'KeyManagerDpe':
if salt_len > cls.SALT_WIDTH:
raise ArgError('Invalid salt length')

if not 0<= args.key_version < 1<<32:
if not 0 <= args.key_version < 1 << 32:
raise ArgError('Invalid key version value')

kmd = cls.create(args.otp_map, args.ecc, args.vmem, args.raw,
Expand Down
4 changes: 2 additions & 2 deletions python/qemu/ot/km/engine.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) 2025 Rivos, Inc.
# Copyright (c) 2025 lowRISC contributors.
# SPDX-License-Identifier: Apache2

"""QEMU OT tool to verify Key Manager DPE test execution
Expand Down Expand Up @@ -165,7 +166,6 @@ def _parse_bytes(cls, value: str) -> bytes:
return ivalue.to_bytes((ivalue.bit_length() + 7) // 8, 'big')
raise ValueError(f'invalid bytes: {value}')


def _build_steps_from_seq(self, seq: ConfigParser) -> \
dict[str, KeyManagerDpeStep]:
module = sys.modules[__name__]
Expand Down Expand Up @@ -279,7 +279,7 @@ def _build_steps_from_log(self, itlog: Iterator[str]) -> \

def _enumerate_steps_from_log(self, itlog: Iterator[str]) -> \
Iterator[tuple[str, dict[str, Union[str, int, bytes, bool]],
Optional[bytes]]]:
Optional[bytes]]]:
step = None
values: dict[str, Union[str, int, bytes, bool]] = {}
result: Optional[bytes] = None
Expand Down
2 changes: 2 additions & 0 deletions python/qemu/ot/lc_ctrl/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Copyright (c) 2024 Rivos, Inc.
# Copyright (c) 2025 lowRISC contributors.
# SPDX-License-Identifier: Apache2

"""LifeCycle tools."""


class LifeCycleError(RuntimeError):
"""Life Cycle Error"""
3 changes: 2 additions & 1 deletion python/qemu/ot/lc_ctrl/const.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) 2025 Rivos, Inc.
# Copyright (c) 2025 lowRISC contributors.
# SPDX-License-Identifier: Apache2

"""Lifecycle helpers.
Expand All @@ -21,7 +22,7 @@ def __init__(self):
self._log = getLogger('lc.const')
self._states: dict[str, tuple[str, str]] = {}
self._tokens: dict[str, str] = {}
self._diversifiers: dict [str, str] = {}
self._diversifiers: dict[str, str] = {}

def load_sv(self, svp: TextIO) -> None:
"""Decode LC information from a System Verilog file.
Expand Down
4 changes: 3 additions & 1 deletion python/qemu/ot/lc_ctrl/lcdmi.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) 2024 Rivos, Inc.
# Copyright (c) 2025 lowRISC contributors.
# SPDX-License-Identifier: Apache2

"""LifeCycle DMI.
Expand Down Expand Up @@ -188,7 +189,8 @@ def transition_token(self) -> bytes:
return token

@transition_token.setter
def transition_token(self, token: Union[bytes, bytearray, str, None]) -> None:
def transition_token(self,
token: Union[bytes, bytearray, str, None]) -> None:
"""Define the transition token as a 16-byte token.

:param token: if None, use an empty zeroed token,
Expand Down
7 changes: 4 additions & 3 deletions python/qemu/ot/otp/const.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) 2023-2025 Rivos, Inc.
# Copyright (c) 2025 lowRISC contributors.
# SPDX-License-Identifier: Apache2

"""Lifecycle helpers.
Expand Down Expand Up @@ -141,17 +142,17 @@ def load_secrets(self, secrets: dict[str, Any]) -> bool:
self._consts['key'] = [
hexlify(kv.to_bytes(sizes['key'], 'big')).decode()
for kd in scrambling['keys']
for kn, kv in kd.items() if kn =='value'
for kn, kv in kd.items() if kn == 'value'
]
self._consts['digest_const'] = [
hexlify(kv.to_bytes(sizes['cnst'], 'big')).decode()
for kd in scrambling['digests']
for kn, kv in kd.items() if kn =='cnst_value'
for kn, kv in kd.items() if kn == 'cnst_value'
]
self._consts['digest_iv'] = [
hexlify(kv.to_bytes(sizes['iv'], 'big')).decode()
for kd in scrambling['digests']
for kn, kv in kd.items() if kn =='iv_value'
for kn, kv in kd.items() if kn == 'iv_value'
]

offset = 0
Expand Down
5 changes: 3 additions & 2 deletions python/qemu/ot/otp/descriptor.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) 2023-2024 Rivos, Inc.
# Copyright (c) 2025 lowRISC contributors.
# SPDX-License-Identifier: Apache2

"""OTP descriptors.
Expand Down Expand Up @@ -228,7 +229,7 @@ def save(self, kind: str, topname: Optional[str], hjname: str,
slots.append(OtpSlotDescriptor(f'{part.name}_DIGEST', offset,
OtpPartition.DIGEST_SIZE, True))
if zeroizable:
offset = part.offset + part.size - OtpPartition.DIGEST_SIZE
offset = part.offset + part.size - OtpPartition.DIGEST_SIZE
slots.append(OtpSlotDescriptor(f'{part.name}_ZER', offset,
OtpPartition.ZER_SIZE, True))

Expand Down Expand Up @@ -264,7 +265,7 @@ def _save_qemu(self, topname: Optional[str], hjname: str, scriptname: str,
part_names.extend((
'OTP_PART_COUNT',
'OTP_ENTRY_DAI = OTP_PART_COUNT, '
'/* Fake partitions for error (...) */',
'/* Fake partitions for error (...) */',
'OTP_ENTRY_KDI, /* Key derivation issue, not really OTP */',
'OTP_ENTRY_COUNT'))
print('typedef enum {', file=cfp)
Expand Down
3 changes: 2 additions & 1 deletion python/qemu/ot/otp/image.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) 2023-2025 Rivos, Inc.
# Copyright (c) 2025 lowRISC contributors.
# SPDX-License-Identifier: Apache2

"""OTP QEMU image.
Expand Down Expand Up @@ -386,7 +387,7 @@ def decode(self, decode: bool = True, wide: int = 0,
for partname in partnames:
if not re.match(part_re, partname, re.IGNORECASE):
continue
if not partname in part_filters:
if partname not in part_filters:
part_filters[partname] = set()
if field == '*':
# any field would match, discard any existing one
Expand Down
5 changes: 3 additions & 2 deletions python/qemu/ot/otp/lifecycle.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) 2023-2024 Rivos, Inc.
# Copyright (c) 2025 lowRISC contributors.
# SPDX-License-Identifier: Apache2

"""Lifecycle helpers.
Expand Down Expand Up @@ -82,8 +83,8 @@ def load(self, svp: TextIO):
self._sequences = sequences
svp.seek(0)
for tmo in re.finditer(r"\s+parameter\s+lc_token_t\s+(\w+)\s+="
r"\s+\{\s+128'h([0-9A-F]+)\s+\};",
svp.getvalue()):
r"\s+\{\s+128'h([0-9A-F]+)\s+\};",
svp.getvalue()):
token, value = tmo.group(1), tmo.group(2)
if token in self._tokens:
raise ValueError(f'Multiple definitions of token {token}')
Expand Down
2 changes: 2 additions & 0 deletions python/qemu/ot/pyot/qemu/wrapper.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) 2023-2025 Rivos, Inc.
# Copyright (c) 2025 lowRISC contributors.
# SPDX-License-Identifier: Apache2

"""QEMU executer wrapper for OpentTitan unit test sequencer.
Expand All @@ -10,6 +11,7 @@

from ..wrapper import Wrapper


class QEMUWrapper(Wrapper):
"""Test execution wrapper using a QEMU virtual machine
"""
Expand Down
3 changes: 2 additions & 1 deletion python/qemu/ot/util/arg.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) 2024-2025 Rivos, Inc.
# Copyright (c) 2025 lowRISC contributors.
# SPDX-License-Identifier: Apache2

"""ArgumentParser extension.
Expand All @@ -8,7 +9,7 @@

# pylint: disable=unused-import
# ruff: noqa: F401
from argparse import ArgumentParser as _ArgumentParser, FileType
from argparse import ArgumentParser as _ArgumentParser
from sys import stderr


Expand Down
4 changes: 3 additions & 1 deletion python/qemu/ot/util/file.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) 2023-2025 Rivos, Inc.
# Copyright (c) 2025 lowRISC contributors.
# SPDX-License-Identifier: Apache2

"""File utilities.
Expand Down Expand Up @@ -106,7 +107,8 @@ def make_vmem_from_elf(elf_file: Union[str, BinaryIO],
is_path = isinstance(vmem_file, str)
with open(vmem_file, 'wt') if is_path else vmem_file as vfp:
print(f'// name: {elfname}', file=vfp)
print(f'// built: {strftime("%Y/%m/%d %H:%M:%S", elftime)}', file=vfp)
print(f'// built: {strftime("%Y/%m/%d %H:%M:%S", elftime)}',
file=vfp)
print(f'// size: {elfstat.st_size}', file=vfp)
print(f'// rawsize: {elf.size}', file=vfp)
print(f'// entrypoint: 0x{elf.entry_point:08x}', file=vfp)
Expand Down
3 changes: 2 additions & 1 deletion python/qemu/ot/util/log.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (c) 2023-2024 Rivos, Inc.
# Copyright (c) 2025 lowRISC contributors.
# SPDX-License-Identifier: Apache2

"""Logging helpers.
Expand Down Expand Up @@ -218,7 +219,7 @@ def handle(self):
if len(buffer) < self.HEADER_SIZE:
continue
header, buffer = (buffer[:self.HEADER_SIZE],
buffer[self.HEADER_SIZE:])
buffer[self.HEADER_SIZE:])
record_len, = sunpack(self.HEADER_FMT, header)
while len(buffer) < record_len:
data = self.rfile.read(4096)
Expand Down
5 changes: 3 additions & 2 deletions python/qemu/ot/util/prince.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

# pylint: disable=missing-docstring


class PrinceCipher:

SBOX4 = [
Expand Down Expand Up @@ -120,8 +121,8 @@ def inv_round(cls, rc: int, key: int, data: int) -> int:

# Run the PRINCE cipher.
# This uses the new keyschedule proposed by Dinur in "Cryptanalytic
# Time-Memory-Data Tradeoffs for FX-Constructions with Applications to PRINCE
# and PRIDE".
# Time-Memory-Data Tradeoffs for FX-Constructions with Applications to
# PRINCE and PRIDE".
@classmethod
def run(cls, data: int, khi: int, klo: int, num_rounds_half: int) -> int:
khi_rot1 = ((khi & 1) << 63) | (khi >> 1)
Expand Down
Loading
Loading