Skip to main content
The CM5 Exaviz platform supports an external TPM connected over I2C or SPI. The TPM is used for platform attestation, measured boot, and sealing secrets (such as LUKS keys or LDAP credentials) to PCR values.

Device access

The TPM is accessible via /dev/tpm0 (raw) and /dev/tpmrm0 (resource-managed). The resource manager is preferred for userspace applications as it handles context saving automatically.
InterfaceKernel driverTypical use
SPItpm_tis_spiMost external TPM modules
I2Ctpm_tis_i2cLow-pin-count designs
I2C userspacei2c-devDebugging and custom tooling
The CM5 does not have an onboard TPM. An external module must be connected to the SPI or I2C header on the Exaviz Cruiser carrier board.

Udev rule

The udev rule for the TPM device node sets group ownership to tss and tags the device for systemd dependency tracking:
/etc/udev/rules.d/99-tpm.rules
SUBSYSTEM=="tpm", TAG+="systemd", MODE="0660", GROUP="tss"
Install and activate:
install -Dm644 tpm.udev /etc/udev/rules.d/99-tpm.rules
udevadm control --reload-rules
udevadm trigger --subsystem-match=tpm
Verify the device node:
ls -l /dev/tpm0 /dev/tpmrm0
Expected:
crw-rw---- 1 root tss 253, 0 ... /dev/tpm0
crw-rw---- 1 root tss 253, 1 ... /dev/tpmrm0
Add application users to the tss group rather than running TPM tools as root:
usermod -aG tss <username>

tpm.sh bring-up script

tpm.sh handles the case where the SPI driver is not loaded automatically. It force-loads spi_bcm2835 and tpm_tis_spi, then blocks until /dev/tpm0 appears (with a 5-second timeout).
tpm.sh
# Force load SPI and TPM modules if not auto-detected
modprobe spi_bcm2835 2>/dev/null
modprobe tpm_tis_spi 2>/dev/null

# Wait for /dev/tpm0 to appear (timeout 5s)
timeout 5 sh -c 'until [ -e /dev/tpm0 ]; do sleep 0.5; done'
This script is suitable as an ExecStartPre command in any service that depends on the TPM:
[Service]
ExecStartPre=/usr/local/bin/tpm.sh
ExecStart=...
If tpm.sh exits non-zero (timeout reached), /dev/tpm0 is absent. Check dmesg | grep -i tpm to diagnose driver probe failures or missing hardware.

Dracut module: 90exaviz

The 90exaviz dracut module embeds TPM, AI accelerator, and PoE bring-up tooling into the initramfs. It ensures the I2C and TPM drivers are available in the early boot environment.
90exaviz/module-setup.sh
# dracut/90exaviz/module-setup.sh
install() {
    # Reusing your 'slammer' for TPM, AI, and PoE
    inst_multiple sh mkdir cat find
    inst_script "$moddir/exaviz-init.sh" "/sbin/exaviz-init"

    # Ensure we have the I2C/SPI drivers if using an external TPM
    hostonly='' instmods i2c-dev tpm_tis_spi tpm_tis_i2c
}

Kernel modules included

ModulePurpose
tpm_tis_spiTPM 2.0 over SPI (TIS interface)
tpm_tis_i2cTPM 2.0 over I2C (TIS interface)
i2c-devI2C userspace device access
hostonly='' forces these modules to be included regardless of whether they are detected on the build host. This is necessary when building the initramfs in a chroot or QEMU environment that does not have the TPM hardware present. Install the module:
install -Dm755 module-setup.sh /usr/lib/dracut/modules.d/90exaviz/module-setup.sh
dracut --force --regenerate-all
Verify the modules are present in the initramfs:
lsinitrd /boot/initramfs-$(uname -r).img | grep tpm

zentyal-tpm-wait.service

zentyal-tpm-wait.service gates Samba AD DC and slapd startup on the TPM being present and readable. It reads PCR banks 0 and 7 to confirm the TPM is operational before LDAP services start.
zentyal-tpm-wait.service
[Unit]
Description=Wait for TPM for Zentyal LDAP Sealing
Before=slapd.service samba-ad-dc.service
ConditionPathExists=/dev/tpm0

[Service]
Type=oneshot
ExecStart=/usr/bin/tpm2_pcrread sha256:0,7
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
Enable the service so it runs on every boot before the directory services start:
systemctl enable zentyal-tpm-wait.service
ConditionPathExists=/dev/tpm0 means the service is skipped silently if the TPM is absent. On systems without a TPM, slapd and samba-ad-dc start normally without the PCR read gate.

PCR values

tpm2_pcrread sha256:0,7 reads two specific PCR banks:
PCRMeasures
0Core system firmware (UEFI)
7Secure Boot policy and state
These values change if the firmware or Secure Boot configuration is modified, breaking any secrets sealed to these PCRs. This is the intended behaviour for detecting tampering. To read the current values manually:
tpm2_pcrread sha256:0,7
sha256:
  0 : 0xA1B2C3D4...
  7 : 0xE5F6A7B8...

Build docs developers (and LLMs) love